Merge "[tracing] Fix combining untyped and typed args in TRACE_EVENT."
diff --git a/Android.bp b/Android.bp
index 6c2a184..e104f17 100644
--- a/Android.bp
+++ b/Android.bp
@@ -16,10194 +16,10234 @@
// GN: //src/profiling/memory:heapprofd
cc_binary {
- name: "heapprofd",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_ext_ipc_ipc",
- ":perfetto_include_perfetto_ext_tracing_core_core",
- ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
- ":perfetto_include_perfetto_profiling_normalize",
- ":perfetto_include_perfetto_protozero_protozero",
- ":perfetto_include_perfetto_tracing_core_core",
- ":perfetto_include_perfetto_tracing_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_daemon",
- ":perfetto_src_profiling_memory_heapprofd_main",
- ":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",
- "src/profiling/memory/main.cc",
- ],
- shared_libs: [
- "libbase",
- "liblog",
- "libprocinfo",
- "libunwindstack",
- ],
- init_rc: [
- "heapprofd.rc",
- ],
- 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",
- ],
- header_libs: [
- "bionic_libc_platform_headers",
- ],
+ name: "heapprofd",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_ipc_ipc",
+ ":perfetto_include_perfetto_ext_tracing_core_core",
+ ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+ ":perfetto_include_perfetto_profiling_normalize",
+ ":perfetto_include_perfetto_protozero_protozero",
+ ":perfetto_include_perfetto_tracing_core_core",
+ ":perfetto_include_perfetto_tracing_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_daemon",
+ ":perfetto_src_profiling_memory_heapprofd_main",
+ ":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",
+ "src/profiling/memory/main.cc",
+ ],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libprocinfo",
+ "libunwindstack",
+ ],
+ init_rc: [
+ "heapprofd.rc",
+ ],
+ 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",
+ ],
+ 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",
+ name: "heapprofd_api_noop",
+ srcs: [
+ "src/profiling/memory/client_api_noop.cc",
],
- symbol_file: "src/profiling/memory/heapprofd_client_api.map.txt",
- },
+ 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
cc_library_shared {
- name: "heapprofd_client",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_src_base_base",
- ":perfetto_src_profiling_memory_malloc_interceptor_bionic_hooks",
- ":perfetto_src_profiling_memory_wrap_allocators",
- ],
- shared_libs: [
- "heapprofd_client_api",
- ],
- static_libs: [
- "libasync_safe",
- ],
- generated_headers: [
- "perfetto_src_base_version_gen_h",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- cflags: [
- "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG",
- ],
- include_dirs: [
- "bionic/libc",
- ],
- header_libs: [
- "bionic_libc_platform_headers",
- ],
+ name: "heapprofd_client",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_src_base_base",
+ ":perfetto_src_profiling_memory_malloc_interceptor_bionic_hooks",
+ ":perfetto_src_profiling_memory_wrap_allocators",
+ ],
+ shared_libs: [
+ "heapprofd_client_api",
+ ],
+ static_libs: [
+ "libasync_safe",
+ ],
+ generated_headers: [
+ "perfetto_src_base_version_gen_h",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ cflags: [
+ "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG",
+ ],
+ include_dirs: [
+ "bionic/libc",
+ ],
+ header_libs: [
+ "bionic_libc_platform_headers",
+ ],
}
// 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",
+ 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",
],
- symbol_file: "src/profiling/memory/heapprofd_client_api.map.txt",
- },
+ 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",
+ 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",
+ ],
+ runtime_libs: [
+ "libdexfile",
+ ],
+ 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",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_src_base_base",
- "src/ipc/protoc_plugin/ipc_plugin.cc",
- ],
- static_libs: [
- "libprotoc",
- ],
- generated_headers: [
- "perfetto_src_base_version_gen_h",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- ],
+ name: "ipc_plugin",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_src_base_base",
+ "src/ipc/protoc_plugin/ipc_plugin.cc",
+ ],
+ static_libs: [
+ "libprotoc",
+ ],
+ generated_headers: [
+ "perfetto_src_base_version_gen_h",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ ],
}
// GN: //:libperfetto
cc_library_shared {
- name: "libperfetto",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_ext_ipc_ipc",
- ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
- ":perfetto_include_perfetto_ext_traced_traced",
- ":perfetto_include_perfetto_ext_tracing_core_core",
- ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
- ":perfetto_include_perfetto_protozero_protozero",
- ":perfetto_include_perfetto_public_public",
- ":perfetto_include_perfetto_tracing_core_core",
- ":perfetto_include_perfetto_tracing_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_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_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_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",
- ":perfetto_src_traced_probes_ps_ps",
- ":perfetto_src_traced_probes_sys_stats_sys_stats",
- ":perfetto_src_traced_probes_system_info_system_info",
- ":perfetto_src_traced_service_service",
- ":perfetto_src_tracing_common",
- ":perfetto_src_tracing_consumer_api_deprecated_consumer_api_deprecated",
- ":perfetto_src_tracing_core_core",
- ":perfetto_src_tracing_core_service",
- ":perfetto_src_tracing_ipc_common",
- ":perfetto_src_tracing_ipc_consumer_consumer",
- ":perfetto_src_tracing_ipc_producer_producer",
- ":perfetto_src_tracing_ipc_service_service",
- ],
- host_supported: true,
- 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",
- "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",
- ],
- target: {
- android: {
- shared_libs: [
- "liblog",
- ],
+ name: "libperfetto",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_ipc_ipc",
+ ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
+ ":perfetto_include_perfetto_ext_traced_traced",
+ ":perfetto_include_perfetto_ext_tracing_core_core",
+ ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+ ":perfetto_include_perfetto_protozero_protozero",
+ ":perfetto_include_perfetto_public_public",
+ ":perfetto_include_perfetto_tracing_core_core",
+ ":perfetto_include_perfetto_tracing_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_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_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_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",
+ ":perfetto_src_traced_probes_ps_ps",
+ ":perfetto_src_traced_probes_sys_stats_sys_stats",
+ ":perfetto_src_traced_probes_system_info_system_info",
+ ":perfetto_src_traced_service_service",
+ ":perfetto_src_tracing_common",
+ ":perfetto_src_tracing_consumer_api_deprecated_consumer_api_deprecated",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ ":perfetto_src_tracing_ipc_service_service",
+ ],
+ host_supported: true,
+ 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",
+ "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",
+ ],
+ target: {
+ android: {
+ shared_libs: [
+ "liblog",
+ ],
+ },
},
- },
}
// GN: //src/android_internal:libperfetto_android_internal
cc_library_shared {
- name: "libperfetto_android_internal",
- srcs: [
- ":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",
- ],
- 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",
- "libcutils",
- "libhidlbase",
- "libincident",
- "liblog",
- "libservices",
- "libstatssocket",
- "libtracingproxy",
- "libutils",
- ],
- static_libs: [
- "libhealthhalutils",
- "libstatslog_perfetto",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- product_variables: {
- pdk: {
- enabled: false,
- },
- },
+ name: "libperfetto_android_internal",
+ srcs: [
+ ":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",
+ ],
+ 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",
+ "libcutils",
+ "libhidlbase",
+ "libincident",
+ "liblog",
+ "libservices",
+ "libstatssocket",
+ "libtracingproxy",
+ "libutils",
+ ],
+ static_libs: [
+ "libhealthhalutils",
+ "libstatslog_perfetto",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
}
// GN: //:libperfetto_client_experimental
cc_library_static {
- name: "libperfetto_client_experimental",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_ext_ipc_ipc",
- ":perfetto_include_perfetto_ext_tracing_core_core",
- ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
- ":perfetto_include_perfetto_protozero_protozero",
- ":perfetto_include_perfetto_tracing_core_core",
- ":perfetto_include_perfetto_tracing_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_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",
- ":perfetto_src_tracing_core_core",
- ":perfetto_src_tracing_core_service",
- ":perfetto_src_tracing_in_process_backend",
- ":perfetto_src_tracing_ipc_common",
- ":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_system_backend",
- ],
- shared_libs: [
- "liblog",
- ],
- 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",
- "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",
- ],
- export_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",
- ],
- apex_available: [
- "//apex_available:platform",
- "com.android.art",
- "com.android.art.debug",
- ],
- min_sdk_version: "S",
+ name: "libperfetto_client_experimental",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_ipc_ipc",
+ ":perfetto_include_perfetto_ext_tracing_core_core",
+ ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+ ":perfetto_include_perfetto_protozero_protozero",
+ ":perfetto_include_perfetto_tracing_core_core",
+ ":perfetto_include_perfetto_tracing_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_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",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_in_process_backend",
+ ":perfetto_src_tracing_ipc_common",
+ ":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_system_backend",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ 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",
+ "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",
+ ],
+ export_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",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.art",
+ "com.android.art.debug",
+ ],
+ min_sdk_version: "S",
}
// GN: //src/perfetto_cmd:perfetto
cc_binary {
- name: "perfetto",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_ext_ipc_ipc",
- ":perfetto_include_perfetto_ext_traced_traced",
- ":perfetto_include_perfetto_ext_tracing_core_core",
- ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
- ":perfetto_include_perfetto_protozero_protozero",
- ":perfetto_include_perfetto_tracing_core_core",
- ":perfetto_include_perfetto_tracing_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_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_cmd",
- ":perfetto_src_perfetto_cmd_protos_gen",
- ":perfetto_src_perfetto_cmd_trigger_producer",
- ":perfetto_src_protozero_protozero",
- ":perfetto_src_tracing_common",
- ":perfetto_src_tracing_core_core",
- ":perfetto_src_tracing_ipc_common",
- ":perfetto_src_tracing_ipc_consumer_consumer",
- ":perfetto_src_tracing_ipc_producer_producer",
- "src/perfetto_cmd/main.cc",
- ],
- shared_libs: [
- "liblog",
- "libz",
- ],
- 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",
- "perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
- "perfetto_src_perfetto_cmd_protos_gen_headers",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_HIDDEN",
- ],
+ name: "perfetto",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_ipc_ipc",
+ ":perfetto_include_perfetto_ext_traced_traced",
+ ":perfetto_include_perfetto_ext_tracing_core_core",
+ ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+ ":perfetto_include_perfetto_protozero_protozero",
+ ":perfetto_include_perfetto_tracing_core_core",
+ ":perfetto_include_perfetto_tracing_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_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_cmd",
+ ":perfetto_src_perfetto_cmd_protos_gen",
+ ":perfetto_src_perfetto_cmd_trigger_producer",
+ ":perfetto_src_protozero_protozero",
+ ":perfetto_src_tracing_common",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ "src/perfetto_cmd/main.cc",
+ ],
+ shared_libs: [
+ "liblog",
+ "libz",
+ ],
+ 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",
+ "perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
+ "perfetto_src_perfetto_cmd_protos_gen_headers",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ "-DHAVE_HIDDEN",
+ ],
}
// GN: //test/cts:perfetto_cts_deps
cc_library_static {
- name: "perfetto_cts_deps",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_ext_ipc_ipc",
- ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
- ":perfetto_include_perfetto_ext_traced_traced",
- ":perfetto_include_perfetto_ext_tracing_core_core",
- ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
- ":perfetto_include_perfetto_protozero_protozero",
- ":perfetto_include_perfetto_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_cpp_gen",
- ":perfetto_protos_perfetto_trace_android_zero_gen",
- ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
- ":perfetto_protos_perfetto_trace_chrome_zero_gen",
- ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
- ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
- ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
- ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
- ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
- ":perfetto_protos_perfetto_trace_gpu_zero_gen",
- ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
- ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
- ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
- ":perfetto_protos_perfetto_trace_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
- ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
- ":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_profiling_cpp_gen",
- ":perfetto_protos_perfetto_trace_profiling_zero_gen",
- ":perfetto_protos_perfetto_trace_ps_cpp_gen",
- ":perfetto_protos_perfetto_trace_ps_zero_gen",
- ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
- ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
- ":perfetto_protos_perfetto_trace_system_info_cpp_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_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_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_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",
- ":perfetto_src_traced_probes_sys_stats_sys_stats",
- ":perfetto_src_traced_probes_system_info_system_info",
- ":perfetto_src_tracing_common",
- ":perfetto_src_tracing_core_core",
- ":perfetto_src_tracing_core_service",
- ":perfetto_src_tracing_ipc_common",
- ":perfetto_src_tracing_ipc_consumer_consumer",
- ":perfetto_src_tracing_ipc_producer_producer",
- ":perfetto_src_tracing_ipc_service_service",
- ":perfetto_test_end_to_end_integrationtests",
- ":perfetto_test_test_helper",
- "test/cts/device_feature_test_cts.cc",
- "test/cts/end_to_end_integrationtest_cts.cc",
- "test/cts/heapprofd_java_test_cts.cc",
- "test/cts/heapprofd_test_cts.cc",
- "test/cts/traced_perf_test_cts.cc",
- ],
- static_libs: [
- "libgmock",
- "libgtest",
- "libperfetto_client_experimental",
- ],
- whole_static_libs: [
- "perfetto_gtest_logcat_printer",
- ],
- 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_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_android_zero_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
- "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_profiling_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ps_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_system_info_cpp_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",
- ],
- export_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_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_android_zero_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
- "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_profiling_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ps_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_system_info_cpp_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",
- ],
+ name: "perfetto_cts_deps",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_ipc_ipc",
+ ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
+ ":perfetto_include_perfetto_ext_traced_traced",
+ ":perfetto_include_perfetto_ext_tracing_core_core",
+ ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+ ":perfetto_include_perfetto_protozero_protozero",
+ ":perfetto_include_perfetto_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_cpp_gen",
+ ":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
+ ":perfetto_protos_perfetto_trace_chrome_zero_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
+ ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
+ ":perfetto_protos_perfetto_trace_gpu_zero_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+ ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
+ ":perfetto_protos_perfetto_trace_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
+ ":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_profiling_cpp_gen",
+ ":perfetto_protos_perfetto_trace_profiling_zero_gen",
+ ":perfetto_protos_perfetto_trace_ps_cpp_gen",
+ ":perfetto_protos_perfetto_trace_ps_zero_gen",
+ ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
+ ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
+ ":perfetto_protos_perfetto_trace_system_info_cpp_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_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_generator",
+ ":perfetto_src_protozero_filtering_bytecode_parser",
+ ":perfetto_src_protozero_filtering_message_filter",
+ ":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_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",
+ ":perfetto_src_traced_probes_sys_stats_sys_stats",
+ ":perfetto_src_traced_probes_system_info_system_info",
+ ":perfetto_src_tracing_common",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ ":perfetto_src_tracing_ipc_service_service",
+ ":perfetto_test_end_to_end_integrationtests",
+ ":perfetto_test_test_helper",
+ "test/cts/device_feature_test_cts.cc",
+ "test/cts/end_to_end_integrationtest_cts.cc",
+ "test/cts/heapprofd_java_test_cts.cc",
+ "test/cts/heapprofd_test_cts.cc",
+ "test/cts/traced_perf_test_cts.cc",
+ ],
+ static_libs: [
+ "libgmock",
+ "libgtest",
+ "libperfetto_client_experimental",
+ ],
+ whole_static_libs: [
+ "perfetto_gtest_logcat_printer",
+ ],
+ 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_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+ "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_profiling_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ps_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_system_info_cpp_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",
+ ],
+ export_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_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+ "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_profiling_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ps_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_system_info_cpp_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",
+ ],
}
// GN: //test/cts:perfetto_cts_jni_deps
cc_library_static {
- name: "perfetto_cts_jni_deps",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_ext_ipc_ipc",
- ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
- ":perfetto_include_perfetto_ext_traced_traced",
- ":perfetto_include_perfetto_ext_tracing_core_core",
- ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
- ":perfetto_include_perfetto_protozero_protozero",
- ":perfetto_include_perfetto_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_cpp_gen",
- ":perfetto_protos_perfetto_trace_android_zero_gen",
- ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
- ":perfetto_protos_perfetto_trace_chrome_zero_gen",
- ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
- ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
- ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
- ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
- ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
- ":perfetto_protos_perfetto_trace_gpu_zero_gen",
- ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
- ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
- ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
- ":perfetto_protos_perfetto_trace_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
- ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
- ":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_profiling_cpp_gen",
- ":perfetto_protos_perfetto_trace_profiling_zero_gen",
- ":perfetto_protos_perfetto_trace_ps_cpp_gen",
- ":perfetto_protos_perfetto_trace_ps_zero_gen",
- ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
- ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
- ":perfetto_protos_perfetto_trace_system_info_cpp_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_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_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_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",
- ":perfetto_src_traced_probes_sys_stats_sys_stats",
- ":perfetto_src_traced_probes_system_info_system_info",
- ":perfetto_src_tracing_common",
- ":perfetto_src_tracing_core_core",
- ":perfetto_src_tracing_core_service",
- ":perfetto_src_tracing_ipc_common",
- ":perfetto_src_tracing_ipc_consumer_consumer",
- ":perfetto_src_tracing_ipc_producer_producer",
- ":perfetto_src_tracing_ipc_service_service",
- ":perfetto_test_test_helper",
- ],
- 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_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_android_zero_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
- "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_profiling_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ps_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_system_info_cpp_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",
- ],
- export_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_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_android_zero_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
- "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_profiling_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ps_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_system_info_cpp_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",
- ],
+ name: "perfetto_cts_jni_deps",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_ipc_ipc",
+ ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
+ ":perfetto_include_perfetto_ext_traced_traced",
+ ":perfetto_include_perfetto_ext_tracing_core_core",
+ ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+ ":perfetto_include_perfetto_protozero_protozero",
+ ":perfetto_include_perfetto_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_cpp_gen",
+ ":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
+ ":perfetto_protos_perfetto_trace_chrome_zero_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
+ ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
+ ":perfetto_protos_perfetto_trace_gpu_zero_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+ ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
+ ":perfetto_protos_perfetto_trace_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
+ ":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_profiling_cpp_gen",
+ ":perfetto_protos_perfetto_trace_profiling_zero_gen",
+ ":perfetto_protos_perfetto_trace_ps_cpp_gen",
+ ":perfetto_protos_perfetto_trace_ps_zero_gen",
+ ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
+ ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
+ ":perfetto_protos_perfetto_trace_system_info_cpp_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_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_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_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",
+ ":perfetto_src_traced_probes_sys_stats_sys_stats",
+ ":perfetto_src_traced_probes_system_info_system_info",
+ ":perfetto_src_tracing_common",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ ":perfetto_src_tracing_ipc_service_service",
+ ":perfetto_test_test_helper",
+ ],
+ 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_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+ "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_profiling_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ps_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_system_info_cpp_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",
+ ],
+ export_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_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+ "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_profiling_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ps_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_system_info_cpp_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",
+ ],
}
// GN: //gn:default_deps
cc_defaults {
- name: "perfetto_defaults",
- cflags: [
- "-O2",
- "-Wno-error=return-type",
- "-Wno-sign-compare",
- "-Wno-sign-promo",
- "-Wno-unused-parameter",
- "-fvisibility=hidden",
- ],
- include_dirs: [
- "external/perfetto",
- "external/perfetto/include",
- "external/perfetto/include/perfetto/base/build_configs/android_tree",
- "external/perfetto/src/profiling/memory/include",
- ],
- product_variables: {
- debuggable: {
- cflags: ["-DPERFETTO_BUILD_WITH_ANDROID_USERDEBUG"],
+ name: "perfetto_defaults",
+ cflags: [
+ "-O2",
+ "-Wno-error=return-type",
+ "-Wno-sign-compare",
+ "-Wno-sign-promo",
+ "-Wno-unused-parameter",
+ "-fvisibility=hidden",
+ ],
+ include_dirs: [
+ "external/perfetto",
+ "external/perfetto/include",
+ "external/perfetto/include/perfetto/base/build_configs/android_tree",
+ "external/perfetto/src/profiling/memory/include",
+ ],
+ product_variables: {
+ debuggable: {
+ cflags: ["-DPERFETTO_BUILD_WITH_ANDROID_USERDEBUG"],
+ },
},
- },
- target: {
- android: {
- lto: {
- thin: true,
- },
+ target: {
+ android: {
+ lto: {
+ thin: true,
+ },
+ },
},
- },
}
// GN: //test:perfetto_gtest_logcat_printer
cc_library_static {
- name: "perfetto_gtest_logcat_printer",
- srcs: [
- "test/gtest_logcat_printer.cc",
- ],
- static_libs: [
- "libgmock",
- "libgtest",
- ],
- defaults: [
- "perfetto_defaults",
- ],
+ name: "perfetto_gtest_logcat_printer",
+ srcs: [
+ "test/gtest_logcat_printer.cc",
+ ],
+ static_libs: [
+ "libgmock",
+ "libgtest",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
}
// GN: //include/perfetto/base:base
filegroup {
- name: "perfetto_include_perfetto_base_base",
+ name: "perfetto_include_perfetto_base_base",
}
// GN: //include/perfetto/ext/base:base
filegroup {
- name: "perfetto_include_perfetto_ext_base_base",
+ name: "perfetto_include_perfetto_ext_base_base",
}
// GN: //include/perfetto/ext/ipc:ipc
filegroup {
- name: "perfetto_include_perfetto_ext_ipc_ipc",
+ name: "perfetto_include_perfetto_ext_ipc_ipc",
}
// GN: //include/perfetto/ext/trace_processor:export_json
filegroup {
- name: "perfetto_include_perfetto_ext_trace_processor_export_json",
+ 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",
+ 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",
+ name: "perfetto_include_perfetto_ext_traced_sys_stats_counters",
}
// GN: //include/perfetto/ext/traced:traced
filegroup {
- name: "perfetto_include_perfetto_ext_traced_traced",
+ name: "perfetto_include_perfetto_ext_traced_traced",
}
// GN: //include/perfetto/ext/tracing/core:core
filegroup {
- name: "perfetto_include_perfetto_ext_tracing_core_core",
+ name: "perfetto_include_perfetto_ext_tracing_core_core",
}
// GN: //include/perfetto/ext/tracing/ipc:ipc
filegroup {
- name: "perfetto_include_perfetto_ext_tracing_ipc_ipc",
+ name: "perfetto_include_perfetto_ext_tracing_ipc_ipc",
}
// GN: //include/perfetto/profiling:normalize
filegroup {
- name: "perfetto_include_perfetto_profiling_normalize",
+ name: "perfetto_include_perfetto_profiling_normalize",
}
// GN: //include/perfetto/profiling:pprof_builder
filegroup {
- name: "perfetto_include_perfetto_profiling_pprof_builder",
+ name: "perfetto_include_perfetto_profiling_pprof_builder",
}
// GN: //include/perfetto/protozero:protozero
filegroup {
- name: "perfetto_include_perfetto_protozero_protozero",
+ name: "perfetto_include_perfetto_protozero_protozero",
}
// GN: //include/perfetto/public:public
filegroup {
- name: "perfetto_include_perfetto_public_public",
+ name: "perfetto_include_perfetto_public_public",
}
// GN: //include/perfetto/test:test_support
filegroup {
- name: "perfetto_include_perfetto_test_test_support",
+ name: "perfetto_include_perfetto_test_test_support",
}
// GN: //include/perfetto/trace_processor:basic_types
filegroup {
- name: "perfetto_include_perfetto_trace_processor_basic_types",
+ name: "perfetto_include_perfetto_trace_processor_basic_types",
}
// GN: //include/perfetto/trace_processor:storage
filegroup {
- name: "perfetto_include_perfetto_trace_processor_storage",
+ name: "perfetto_include_perfetto_trace_processor_storage",
}
// GN: //include/perfetto/trace_processor:trace_processor
filegroup {
- name: "perfetto_include_perfetto_trace_processor_trace_processor",
+ name: "perfetto_include_perfetto_trace_processor_trace_processor",
}
// GN: //include/perfetto/tracing/core:core
filegroup {
- name: "perfetto_include_perfetto_tracing_core_core",
+ name: "perfetto_include_perfetto_tracing_core_core",
}
// GN: //include/perfetto/tracing/core:forward_decls
filegroup {
- name: "perfetto_include_perfetto_tracing_core_forward_decls",
+ name: "perfetto_include_perfetto_tracing_core_forward_decls",
}
// GN: //include/perfetto/tracing:tracing
filegroup {
- name: "perfetto_include_perfetto_tracing_tracing",
+ name: "perfetto_include_perfetto_tracing_tracing",
}
// GN: //:perfetto_integrationtests
cc_test {
- name: "perfetto_integrationtests",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_ext_ipc_ipc",
- ":perfetto_include_perfetto_ext_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",
- ":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_cpp_gen",
- ":perfetto_protos_perfetto_trace_android_zero_gen",
- ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
- ":perfetto_protos_perfetto_trace_chrome_zero_gen",
- ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
- ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
- ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
- ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
- ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
- ":perfetto_protos_perfetto_trace_gpu_zero_gen",
- ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
- ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
- ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
- ":perfetto_protos_perfetto_trace_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
- ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
- ":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",
- ":perfetto_protos_perfetto_trace_ps_zero_gen",
- ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
- ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
- ":perfetto_protos_perfetto_trace_system_info_cpp_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_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_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",
- ":perfetto_src_profiling_memory_end_to_end_tests",
- ":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_gzip",
- ":perfetto_src_trace_processor_util_interned_message_view",
- ":perfetto_src_trace_processor_util_proto_to_args_parser",
- ":perfetto_src_trace_processor_util_protozero_to_text",
- ":perfetto_src_trace_processor_util_trace_blob_view",
- ":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_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",
- ":perfetto_src_traced_probes_sys_stats_sys_stats",
- ":perfetto_src_traced_probes_system_info_system_info",
- ":perfetto_src_tracing_client_api_without_backends",
- ":perfetto_src_tracing_common",
- ":perfetto_src_tracing_core_core",
- ":perfetto_src_tracing_core_service",
- ":perfetto_src_tracing_in_process_backend",
- ":perfetto_src_tracing_ipc_common",
- ":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_system_backend",
- ":perfetto_src_tracing_test_api_test_support",
- ":perfetto_src_tracing_test_client_api_integrationtests",
- ":perfetto_test_end_to_end_integrationtests",
- ":perfetto_test_test_helper",
- ],
- shared_libs: [
- "heapprofd_client_api",
- "libandroidicu",
- "libbase",
- "liblog",
- "libprocinfo",
- "libsqlite",
- "libunwindstack",
- "libutils",
- "libz",
- ],
- static_libs: [
- "libgmock",
- "libgtest",
- "libperfetto_client_experimental",
- ],
- whole_static_libs: [
- "perfetto_gtest_logcat_printer",
- ],
- 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_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_android_zero_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_cpp_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_zero_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
- "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",
- "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
- "perfetto_protos_perfetto_trace_sys_stats_cpp_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_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",
- ],
- 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",
+ name: "perfetto_integrationtests",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_ipc_ipc",
+ ":perfetto_include_perfetto_ext_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",
+ ":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_cpp_gen",
+ ":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
+ ":perfetto_protos_perfetto_trace_chrome_zero_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
+ ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
+ ":perfetto_protos_perfetto_trace_gpu_zero_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+ ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
+ ":perfetto_protos_perfetto_trace_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
+ ":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",
+ ":perfetto_protos_perfetto_trace_ps_zero_gen",
+ ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
+ ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
+ ":perfetto_protos_perfetto_trace_system_info_cpp_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_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_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",
+ ":perfetto_src_profiling_memory_end_to_end_tests",
+ ":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_generator",
+ ":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_gzip",
+ ":perfetto_src_trace_processor_util_interned_message_view",
+ ":perfetto_src_trace_processor_util_proto_to_args_parser",
+ ":perfetto_src_trace_processor_util_protozero_to_text",
+ ":perfetto_src_trace_processor_util_trace_blob_view",
+ ":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_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",
+ ":perfetto_src_traced_probes_sys_stats_sys_stats",
+ ":perfetto_src_traced_probes_system_info_system_info",
+ ":perfetto_src_tracing_client_api_without_backends",
+ ":perfetto_src_tracing_common",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_in_process_backend",
+ ":perfetto_src_tracing_ipc_common",
+ ":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_system_backend",
+ ":perfetto_src_tracing_test_api_test_support",
+ ":perfetto_src_tracing_test_client_api_integrationtests",
+ ":perfetto_test_end_to_end_integrationtests",
+ ":perfetto_test_test_helper",
+ ],
+ shared_libs: [
+ "heapprofd_client_api",
+ "libandroidicu",
+ "libbase",
+ "liblog",
+ "libprocinfo",
+ "libsqlite",
+ "libunwindstack",
+ "libutils",
+ "libz",
+ ],
+ static_libs: [
+ "libgmock",
+ "libgtest",
+ "libperfetto_client_experimental",
+ ],
+ whole_static_libs: [
+ "perfetto_gtest_logcat_printer",
+ ],
+ 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_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_cpp_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_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+ "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",
+ "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_sys_stats_cpp_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_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",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ "-DHAVE_HIDDEN",
+ "-fno-finite-loops",
+ ],
+ 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",
- "protos/perfetto/common/tracing_service_state.proto",
- "protos/perfetto/common/track_event_descriptor.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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",
- "external/perfetto/protos/perfetto/common/tracing_service_state.gen.cc",
- "external/perfetto/protos/perfetto/common/track_event_descriptor.gen.cc",
- ],
+ 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",
+ "protos/perfetto/common/tracing_service_state.proto",
+ "protos/perfetto/common/track_event_descriptor.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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",
+ "external/perfetto/protos/perfetto/common/tracing_service_state.gen.cc",
+ "external/perfetto/protos/perfetto/common/track_event_descriptor.gen.cc",
+ ],
}
// GN: //protos/perfetto/common:cpp
genrule {
- name: "perfetto_protos_perfetto_common_cpp_gen_headers",
- srcs: [
- "protos/perfetto/common/android_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",
- ],
- 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/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",
- "external/perfetto/protos/perfetto/common/tracing_service_state.gen.h",
- "external/perfetto/protos/perfetto/common/track_event_descriptor.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "protos/perfetto/common/tracing_service_state.proto",
+ "protos/perfetto/common/track_event_descriptor.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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",
+ "external/perfetto/protos/perfetto/common/tracing_service_state.gen.h",
+ "external/perfetto/protos/perfetto/common/track_event_descriptor.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/common:lite
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",
- "protos/perfetto/common/tracing_service_state.proto",
- "protos/perfetto/common/track_event_descriptor.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/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",
- "external/perfetto/protos/perfetto/common/tracing_service_state.pb.cc",
- "external/perfetto/protos/perfetto/common/track_event_descriptor.pb.cc",
- ],
+ 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",
+ "protos/perfetto/common/tracing_service_state.proto",
+ "protos/perfetto/common/track_event_descriptor.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/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",
+ "external/perfetto/protos/perfetto/common/tracing_service_state.pb.cc",
+ "external/perfetto/protos/perfetto/common/track_event_descriptor.pb.cc",
+ ],
}
// GN: //protos/perfetto/common:lite
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",
- "protos/perfetto/common/tracing_service_state.proto",
- "protos/perfetto/common/track_event_descriptor.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/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",
- "external/perfetto/protos/perfetto/common/tracing_service_state.pb.h",
- "external/perfetto/protos/perfetto/common/track_event_descriptor.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "protos/perfetto/common/tracing_service_state.proto",
+ "protos/perfetto/common/track_event_descriptor.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/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",
+ "external/perfetto/protos/perfetto/common/tracing_service_state.pb.h",
+ "external/perfetto/protos/perfetto/common/track_event_descriptor.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/common:zero
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",
- "protos/perfetto/common/tracing_service_state.proto",
- "protos/perfetto/common/track_event_descriptor.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/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",
- "external/perfetto/protos/perfetto/common/tracing_service_state.pbzero.cc",
- "external/perfetto/protos/perfetto/common/track_event_descriptor.pbzero.cc",
- ],
+ 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",
+ "protos/perfetto/common/tracing_service_state.proto",
+ "protos/perfetto/common/track_event_descriptor.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/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",
+ "external/perfetto/protos/perfetto/common/tracing_service_state.pbzero.cc",
+ "external/perfetto/protos/perfetto/common/track_event_descriptor.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/common:zero
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",
- "protos/perfetto/common/tracing_service_state.proto",
- "protos/perfetto/common/track_event_descriptor.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/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",
- "external/perfetto/protos/perfetto/common/tracing_service_state.pbzero.h",
- "external/perfetto/protos/perfetto/common/track_event_descriptor.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "protos/perfetto/common/tracing_service_state.proto",
+ "protos/perfetto/common/track_event_descriptor.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/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",
+ "external/perfetto/protos/perfetto/common/tracing_service_state.pbzero.h",
+ "external/perfetto/protos/perfetto/common/track_event_descriptor.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/android:cpp
genrule {
- name: "perfetto_protos_perfetto_config_android_cpp_gen",
- srcs: [
- "protos/perfetto/config/android/android_log_config.proto",
- "protos/perfetto/config/android/android_polled_state_config.proto",
- "protos/perfetto/config/android/packages_list_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/android/android_log_config.gen.cc",
- "external/perfetto/protos/perfetto/config/android/android_polled_state_config.gen.cc",
- "external/perfetto/protos/perfetto/config/android/packages_list_config.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_config_android_cpp_gen",
+ srcs: [
+ "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",
+ ],
+ 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/android/android_log_config.gen.cc",
+ "external/perfetto/protos/perfetto/config/android/android_polled_state_config.gen.cc",
+ "external/perfetto/protos/perfetto/config/android/packages_list_config.gen.cc",
+ ],
}
// GN: //protos/perfetto/config/android:cpp
genrule {
- name: "perfetto_protos_perfetto_config_android_cpp_gen_headers",
- srcs: [
- "protos/perfetto/config/android/android_log_config.proto",
- "protos/perfetto/config/android/android_polled_state_config.proto",
- "protos/perfetto/config/android/packages_list_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/android/android_log_config.gen.h",
- "external/perfetto/protos/perfetto/config/android/android_polled_state_config.gen.h",
- "external/perfetto/protos/perfetto/config/android/packages_list_config.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_android_cpp_gen_headers",
+ srcs: [
+ "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",
+ ],
+ 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/android/android_log_config.gen.h",
+ "external/perfetto/protos/perfetto/config/android/android_polled_state_config.gen.h",
+ "external/perfetto/protos/perfetto/config/android/packages_list_config.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/android:lite
genrule {
- name: "perfetto_protos_perfetto_config_android_lite_gen",
- srcs: [
- "protos/perfetto/config/android/android_log_config.proto",
- "protos/perfetto/config/android/android_polled_state_config.proto",
- "protos/perfetto/config/android/packages_list_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/android/android_log_config.pb.cc",
- "external/perfetto/protos/perfetto/config/android/android_polled_state_config.pb.cc",
- "external/perfetto/protos/perfetto/config/android/packages_list_config.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_config_android_lite_gen",
+ srcs: [
+ "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",
+ ],
+ 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/android/android_log_config.pb.cc",
+ "external/perfetto/protos/perfetto/config/android/android_polled_state_config.pb.cc",
+ "external/perfetto/protos/perfetto/config/android/packages_list_config.pb.cc",
+ ],
}
// GN: //protos/perfetto/config/android:lite
genrule {
- name: "perfetto_protos_perfetto_config_android_lite_gen_headers",
- srcs: [
- "protos/perfetto/config/android/android_log_config.proto",
- "protos/perfetto/config/android/android_polled_state_config.proto",
- "protos/perfetto/config/android/packages_list_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/android/android_log_config.pb.h",
- "external/perfetto/protos/perfetto/config/android/android_polled_state_config.pb.h",
- "external/perfetto/protos/perfetto/config/android/packages_list_config.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_android_lite_gen_headers",
+ srcs: [
+ "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",
+ ],
+ 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/android/android_log_config.pb.h",
+ "external/perfetto/protos/perfetto/config/android/android_polled_state_config.pb.h",
+ "external/perfetto/protos/perfetto/config/android/packages_list_config.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/android:zero
genrule {
- name: "perfetto_protos_perfetto_config_android_zero_gen",
- srcs: [
- "protos/perfetto/config/android/android_log_config.proto",
- "protos/perfetto/config/android/android_polled_state_config.proto",
- "protos/perfetto/config/android/packages_list_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/android/android_log_config.pbzero.cc",
- "external/perfetto/protos/perfetto/config/android/android_polled_state_config.pbzero.cc",
- "external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_config_android_zero_gen",
+ srcs: [
+ "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",
+ ],
+ 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/android/android_log_config.pbzero.cc",
+ "external/perfetto/protos/perfetto/config/android/android_polled_state_config.pbzero.cc",
+ "external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/config/android:zero
genrule {
- name: "perfetto_protos_perfetto_config_android_zero_gen_headers",
- srcs: [
- "protos/perfetto/config/android/android_log_config.proto",
- "protos/perfetto/config/android/android_polled_state_config.proto",
- "protos/perfetto/config/android/packages_list_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/android/android_log_config.pbzero.h",
- "external/perfetto/protos/perfetto/config/android/android_polled_state_config.pbzero.h",
- "external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_android_zero_gen_headers",
+ srcs: [
+ "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",
+ ],
+ 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/android/android_log_config.pbzero.h",
+ "external/perfetto/protos/perfetto/config/android/android_polled_state_config.pbzero.h",
+ "external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config:cpp
genrule {
- name: "perfetto_protos_perfetto_config_cpp_gen",
- srcs: [
- "protos/perfetto/config/chrome/chrome_config.proto",
- "protos/perfetto/config/data_source_config.proto",
- "protos/perfetto/config/interceptor_config.proto",
- "protos/perfetto/config/stress_test_config.proto",
- "protos/perfetto/config/test_config.proto",
- "protos/perfetto/config/trace_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/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",
- ],
+ name: "perfetto_protos_perfetto_config_cpp_gen",
+ srcs: [
+ "protos/perfetto/config/chrome/chrome_config.proto",
+ "protos/perfetto/config/data_source_config.proto",
+ "protos/perfetto/config/interceptor_config.proto",
+ "protos/perfetto/config/stress_test_config.proto",
+ "protos/perfetto/config/test_config.proto",
+ "protos/perfetto/config/trace_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/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",
+ ],
}
// GN: //protos/perfetto/config:cpp
genrule {
- name: "perfetto_protos_perfetto_config_cpp_gen_headers",
- srcs: [
- "protos/perfetto/config/chrome/chrome_config.proto",
- "protos/perfetto/config/data_source_config.proto",
- "protos/perfetto/config/interceptor_config.proto",
- "protos/perfetto/config/stress_test_config.proto",
- "protos/perfetto/config/test_config.proto",
- "protos/perfetto/config/trace_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/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",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/config/chrome/chrome_config.proto",
+ "protos/perfetto/config/data_source_config.proto",
+ "protos/perfetto/config/interceptor_config.proto",
+ "protos/perfetto/config/stress_test_config.proto",
+ "protos/perfetto/config/test_config.proto",
+ "protos/perfetto/config/trace_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/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",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// 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",
- ],
+ 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",
- srcs: [
- "protos/perfetto/config/ftrace/ftrace_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/ftrace/ftrace_config.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_config_ftrace_cpp_gen",
+ srcs: [
+ "protos/perfetto/config/ftrace/ftrace_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/ftrace/ftrace_config.gen.cc",
+ ],
}
// GN: //protos/perfetto/config/ftrace:cpp
genrule {
- name: "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
- srcs: [
- "protos/perfetto/config/ftrace/ftrace_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/ftrace/ftrace_config.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/config/ftrace/ftrace_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/ftrace/ftrace_config.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/ftrace:lite
genrule {
- name: "perfetto_protos_perfetto_config_ftrace_lite_gen",
- srcs: [
- "protos/perfetto/config/ftrace/ftrace_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_config_ftrace_lite_gen",
+ srcs: [
+ "protos/perfetto/config/ftrace/ftrace_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.cc",
+ ],
}
// GN: //protos/perfetto/config/ftrace:lite
genrule {
- name: "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
- srcs: [
- "protos/perfetto/config/ftrace/ftrace_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/config/ftrace/ftrace_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/ftrace:zero
genrule {
- name: "perfetto_protos_perfetto_config_ftrace_zero_gen",
- srcs: [
- "protos/perfetto/config/ftrace/ftrace_config.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_config_ftrace_zero_gen",
+ srcs: [
+ "protos/perfetto/config/ftrace/ftrace_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/config/ftrace:zero
genrule {
- name: "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
- srcs: [
- "protos/perfetto/config/ftrace/ftrace_config.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/config/ftrace/ftrace_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/gpu:cpp
genrule {
- name: "perfetto_protos_perfetto_config_gpu_cpp_gen",
- srcs: [
- "protos/perfetto/config/gpu/gpu_counter_config.proto",
- "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.gen.cc",
- "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_config_gpu_cpp_gen",
+ srcs: [
+ "protos/perfetto/config/gpu/gpu_counter_config.proto",
+ "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.gen.cc",
+ "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.gen.cc",
+ ],
}
// GN: //protos/perfetto/config/gpu:cpp
genrule {
- name: "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
- srcs: [
- "protos/perfetto/config/gpu/gpu_counter_config.proto",
- "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.gen.h",
- "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/config/gpu/gpu_counter_config.proto",
+ "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.gen.h",
+ "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/gpu:lite
genrule {
- name: "perfetto_protos_perfetto_config_gpu_lite_gen",
- srcs: [
- "protos/perfetto/config/gpu/gpu_counter_config.proto",
- "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.pb.cc",
- "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_config_gpu_lite_gen",
+ srcs: [
+ "protos/perfetto/config/gpu/gpu_counter_config.proto",
+ "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.pb.cc",
+ "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.pb.cc",
+ ],
}
// GN: //protos/perfetto/config/gpu:lite
genrule {
- name: "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
- srcs: [
- "protos/perfetto/config/gpu/gpu_counter_config.proto",
- "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.pb.h",
- "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/config/gpu/gpu_counter_config.proto",
+ "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.pb.h",
+ "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/gpu:zero
genrule {
- name: "perfetto_protos_perfetto_config_gpu_zero_gen",
- srcs: [
- "protos/perfetto/config/gpu/gpu_counter_config.proto",
- "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.pbzero.cc",
- "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_config_gpu_zero_gen",
+ srcs: [
+ "protos/perfetto/config/gpu/gpu_counter_config.proto",
+ "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.pbzero.cc",
+ "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/config/gpu:zero
genrule {
- name: "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
- srcs: [
- "protos/perfetto/config/gpu/gpu_counter_config.proto",
- "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.pbzero.h",
- "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/config/gpu/gpu_counter_config.proto",
+ "protos/perfetto/config/gpu/vulkan_memory_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/gpu/gpu_counter_config.pbzero.h",
+ "external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/inode_file:cpp
genrule {
- name: "perfetto_protos_perfetto_config_inode_file_cpp_gen",
- srcs: [
- "protos/perfetto/config/inode_file/inode_file_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/inode_file/inode_file_config.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_config_inode_file_cpp_gen",
+ srcs: [
+ "protos/perfetto/config/inode_file/inode_file_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/inode_file/inode_file_config.gen.cc",
+ ],
}
// GN: //protos/perfetto/config/inode_file:cpp
genrule {
- name: "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
- srcs: [
- "protos/perfetto/config/inode_file/inode_file_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/inode_file/inode_file_config.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/config/inode_file/inode_file_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/inode_file/inode_file_config.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/inode_file:lite
genrule {
- name: "perfetto_protos_perfetto_config_inode_file_lite_gen",
- srcs: [
- "protos/perfetto/config/inode_file/inode_file_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_config_inode_file_lite_gen",
+ srcs: [
+ "protos/perfetto/config/inode_file/inode_file_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.cc",
+ ],
}
// GN: //protos/perfetto/config/inode_file:lite
genrule {
- name: "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
- srcs: [
- "protos/perfetto/config/inode_file/inode_file_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/config/inode_file/inode_file_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/inode_file:zero
genrule {
- name: "perfetto_protos_perfetto_config_inode_file_zero_gen",
- srcs: [
- "protos/perfetto/config/inode_file/inode_file_config.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_config_inode_file_zero_gen",
+ srcs: [
+ "protos/perfetto/config/inode_file/inode_file_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/config/inode_file:zero
genrule {
- name: "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
- srcs: [
- "protos/perfetto/config/inode_file/inode_file_config.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/config/inode_file/inode_file_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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",
- ],
- 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/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",
- ],
+ 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",
+ ],
+ 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/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",
+ ],
}
// GN: //protos/perfetto/config:lite
genrule {
- name: "perfetto_protos_perfetto_config_lite_gen_headers",
- 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",
- ],
- 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/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",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_lite_gen_headers",
+ 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",
+ ],
+ 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/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",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// 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",
- ],
+ 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",
- srcs: [
- "protos/perfetto/config/power/android_power_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/power/android_power_config.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_config_power_cpp_gen",
+ srcs: [
+ "protos/perfetto/config/power/android_power_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/power/android_power_config.gen.cc",
+ ],
}
// GN: //protos/perfetto/config/power:cpp
genrule {
- name: "perfetto_protos_perfetto_config_power_cpp_gen_headers",
- srcs: [
- "protos/perfetto/config/power/android_power_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/power/android_power_config.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_power_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/config/power/android_power_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/power/android_power_config.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/power:lite
genrule {
- name: "perfetto_protos_perfetto_config_power_lite_gen",
- srcs: [
- "protos/perfetto/config/power/android_power_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/power/android_power_config.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_config_power_lite_gen",
+ srcs: [
+ "protos/perfetto/config/power/android_power_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/power/android_power_config.pb.cc",
+ ],
}
// GN: //protos/perfetto/config/power:lite
genrule {
- name: "perfetto_protos_perfetto_config_power_lite_gen_headers",
- srcs: [
- "protos/perfetto/config/power/android_power_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/power/android_power_config.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_power_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/config/power/android_power_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/power/android_power_config.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/power:zero
genrule {
- name: "perfetto_protos_perfetto_config_power_zero_gen",
- srcs: [
- "protos/perfetto/config/power/android_power_config.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/power/android_power_config.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_config_power_zero_gen",
+ srcs: [
+ "protos/perfetto/config/power/android_power_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/power/android_power_config.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/config/power:zero
genrule {
- name: "perfetto_protos_perfetto_config_power_zero_gen_headers",
- srcs: [
- "protos/perfetto/config/power/android_power_config.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/power/android_power_config.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_power_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/config/power/android_power_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/power/android_power_config.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/process_stats:cpp
genrule {
- name: "perfetto_protos_perfetto_config_process_stats_cpp_gen",
- srcs: [
- "protos/perfetto/config/process_stats/process_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/process_stats/process_stats_config.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_config_process_stats_cpp_gen",
+ srcs: [
+ "protos/perfetto/config/process_stats/process_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/process_stats/process_stats_config.gen.cc",
+ ],
}
// GN: //protos/perfetto/config/process_stats:cpp
genrule {
- name: "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
- srcs: [
- "protos/perfetto/config/process_stats/process_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/process_stats/process_stats_config.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/config/process_stats/process_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/process_stats/process_stats_config.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/process_stats:lite
genrule {
- name: "perfetto_protos_perfetto_config_process_stats_lite_gen",
- srcs: [
- "protos/perfetto/config/process_stats/process_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_config_process_stats_lite_gen",
+ srcs: [
+ "protos/perfetto/config/process_stats/process_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pb.cc",
+ ],
}
// GN: //protos/perfetto/config/process_stats:lite
genrule {
- name: "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
- srcs: [
- "protos/perfetto/config/process_stats/process_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/config/process_stats/process_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/process_stats:zero
genrule {
- name: "perfetto_protos_perfetto_config_process_stats_zero_gen",
- srcs: [
- "protos/perfetto/config/process_stats/process_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_config_process_stats_zero_gen",
+ srcs: [
+ "protos/perfetto/config/process_stats/process_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/config/process_stats:zero
genrule {
- name: "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
- srcs: [
- "protos/perfetto/config/process_stats/process_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/config/process_stats/process_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/profiling:cpp
genrule {
- name: "perfetto_protos_perfetto_config_profiling_cpp_gen",
- srcs: [
- "protos/perfetto/config/profiling/heapprofd_config.proto",
- "protos/perfetto/config/profiling/java_hprof_config.proto",
- "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.gen.cc",
- "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.gen.cc",
- "external/perfetto/protos/perfetto/config/profiling/perf_event_config.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_config_profiling_cpp_gen",
+ srcs: [
+ "protos/perfetto/config/profiling/heapprofd_config.proto",
+ "protos/perfetto/config/profiling/java_hprof_config.proto",
+ "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.gen.cc",
+ "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.gen.cc",
+ "external/perfetto/protos/perfetto/config/profiling/perf_event_config.gen.cc",
+ ],
}
// GN: //protos/perfetto/config/profiling:cpp
genrule {
- name: "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
- srcs: [
- "protos/perfetto/config/profiling/heapprofd_config.proto",
- "protos/perfetto/config/profiling/java_hprof_config.proto",
- "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.gen.h",
- "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.gen.h",
- "external/perfetto/protos/perfetto/config/profiling/perf_event_config.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/config/profiling/heapprofd_config.proto",
+ "protos/perfetto/config/profiling/java_hprof_config.proto",
+ "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.gen.h",
+ "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.gen.h",
+ "external/perfetto/protos/perfetto/config/profiling/perf_event_config.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/profiling:lite
genrule {
- name: "perfetto_protos_perfetto_config_profiling_lite_gen",
- srcs: [
- "protos/perfetto/config/profiling/heapprofd_config.proto",
- "protos/perfetto/config/profiling/java_hprof_config.proto",
- "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.pb.cc",
- "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pb.cc",
- "external/perfetto/protos/perfetto/config/profiling/perf_event_config.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_config_profiling_lite_gen",
+ srcs: [
+ "protos/perfetto/config/profiling/heapprofd_config.proto",
+ "protos/perfetto/config/profiling/java_hprof_config.proto",
+ "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.pb.cc",
+ "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pb.cc",
+ "external/perfetto/protos/perfetto/config/profiling/perf_event_config.pb.cc",
+ ],
}
// GN: //protos/perfetto/config/profiling:lite
genrule {
- name: "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
- srcs: [
- "protos/perfetto/config/profiling/heapprofd_config.proto",
- "protos/perfetto/config/profiling/java_hprof_config.proto",
- "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.pb.h",
- "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pb.h",
- "external/perfetto/protos/perfetto/config/profiling/perf_event_config.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/config/profiling/heapprofd_config.proto",
+ "protos/perfetto/config/profiling/java_hprof_config.proto",
+ "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.pb.h",
+ "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pb.h",
+ "external/perfetto/protos/perfetto/config/profiling/perf_event_config.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/profiling:zero
genrule {
- name: "perfetto_protos_perfetto_config_profiling_zero_gen",
- srcs: [
- "protos/perfetto/config/profiling/heapprofd_config.proto",
- "protos/perfetto/config/profiling/java_hprof_config.proto",
- "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.pbzero.cc",
- "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pbzero.cc",
- "external/perfetto/protos/perfetto/config/profiling/perf_event_config.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_config_profiling_zero_gen",
+ srcs: [
+ "protos/perfetto/config/profiling/heapprofd_config.proto",
+ "protos/perfetto/config/profiling/java_hprof_config.proto",
+ "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.pbzero.cc",
+ "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pbzero.cc",
+ "external/perfetto/protos/perfetto/config/profiling/perf_event_config.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/config/profiling:zero
genrule {
- name: "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
- srcs: [
- "protos/perfetto/config/profiling/heapprofd_config.proto",
- "protos/perfetto/config/profiling/java_hprof_config.proto",
- "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.pbzero.h",
- "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pbzero.h",
- "external/perfetto/protos/perfetto/config/profiling/perf_event_config.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/config/profiling/heapprofd_config.proto",
+ "protos/perfetto/config/profiling/java_hprof_config.proto",
+ "protos/perfetto/config/profiling/perf_event_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/profiling/heapprofd_config.pbzero.h",
+ "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pbzero.h",
+ "external/perfetto/protos/perfetto/config/profiling/perf_event_config.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/sys_stats:cpp
genrule {
- name: "perfetto_protos_perfetto_config_sys_stats_cpp_gen",
- srcs: [
- "protos/perfetto/config/sys_stats/sys_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/sys_stats/sys_stats_config.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_config_sys_stats_cpp_gen",
+ srcs: [
+ "protos/perfetto/config/sys_stats/sys_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/sys_stats/sys_stats_config.gen.cc",
+ ],
}
// GN: //protos/perfetto/config/sys_stats:cpp
genrule {
- name: "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
- srcs: [
- "protos/perfetto/config/sys_stats/sys_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/sys_stats/sys_stats_config.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/config/sys_stats/sys_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/sys_stats/sys_stats_config.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/sys_stats:lite
genrule {
- name: "perfetto_protos_perfetto_config_sys_stats_lite_gen",
- srcs: [
- "protos/perfetto/config/sys_stats/sys_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_config_sys_stats_lite_gen",
+ srcs: [
+ "protos/perfetto/config/sys_stats/sys_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pb.cc",
+ ],
}
// GN: //protos/perfetto/config/sys_stats:lite
genrule {
- name: "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
- srcs: [
- "protos/perfetto/config/sys_stats/sys_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/config/sys_stats/sys_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/sys_stats:zero
genrule {
- name: "perfetto_protos_perfetto_config_sys_stats_zero_gen",
- srcs: [
- "protos/perfetto/config/sys_stats/sys_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_config_sys_stats_zero_gen",
+ srcs: [
+ "protos/perfetto/config/sys_stats/sys_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/config/sys_stats:zero
genrule {
- name: "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
- srcs: [
- "protos/perfetto/config/sys_stats/sys_stats_config.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/config/sys_stats/sys_stats_config.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/track_event:cpp
genrule {
- name: "perfetto_protos_perfetto_config_track_event_cpp_gen",
- srcs: [
- "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_config_track_event_cpp_gen",
+ srcs: [
+ "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.gen.cc",
+ ],
}
// GN: //protos/perfetto/config/track_event:cpp
genrule {
- name: "perfetto_protos_perfetto_config_track_event_cpp_gen_headers",
- srcs: [
- "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_track_event_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/track_event:lite
genrule {
- name: "perfetto_protos_perfetto_config_track_event_lite_gen",
- srcs: [
- "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_config_track_event_lite_gen",
+ srcs: [
+ "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.pb.cc",
+ ],
}
// GN: //protos/perfetto/config/track_event:lite
genrule {
- name: "perfetto_protos_perfetto_config_track_event_lite_gen_headers",
- srcs: [
- "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_track_event_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config/track_event:zero
genrule {
- name: "perfetto_protos_perfetto_config_track_event_zero_gen",
- srcs: [
- "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_config_track_event_zero_gen",
+ srcs: [
+ "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/config/track_event:zero
genrule {
- name: "perfetto_protos_perfetto_config_track_event_zero_gen_headers",
- srcs: [
- "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_track_event_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/config/track_event/track_event_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/track_event/track_event_config.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/config:zero
genrule {
- name: "perfetto_protos_perfetto_config_zero_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",
- ],
- 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/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",
- ],
+ name: "perfetto_protos_perfetto_config_zero_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",
+ ],
+ 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/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",
+ ],
}
// GN: //protos/perfetto/config:zero
genrule {
- name: "perfetto_protos_perfetto_config_zero_gen_headers",
- 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",
- ],
- 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/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",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_config_zero_gen_headers",
+ 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",
+ ],
+ 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/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",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/ipc:cpp
genrule {
- name: "perfetto_protos_perfetto_ipc_cpp_gen",
- srcs: [
- "protos/perfetto/ipc/consumer_port.proto",
- "protos/perfetto/ipc/producer_port.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/ipc/consumer_port.gen.cc",
- "external/perfetto/protos/perfetto/ipc/producer_port.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_ipc_cpp_gen",
+ srcs: [
+ "protos/perfetto/ipc/consumer_port.proto",
+ "protos/perfetto/ipc/producer_port.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/ipc/consumer_port.gen.cc",
+ "external/perfetto/protos/perfetto/ipc/producer_port.gen.cc",
+ ],
}
// GN: //protos/perfetto/ipc:cpp
genrule {
- name: "perfetto_protos_perfetto_ipc_cpp_gen_headers",
- srcs: [
- "protos/perfetto/ipc/consumer_port.proto",
- "protos/perfetto/ipc/producer_port.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/ipc/consumer_port.gen.h",
- "external/perfetto/protos/perfetto/ipc/producer_port.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_ipc_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/ipc/consumer_port.proto",
+ "protos/perfetto/ipc/producer_port.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/ipc/consumer_port.gen.h",
+ "external/perfetto/protos/perfetto/ipc/producer_port.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/ipc:ipc
genrule {
- name: "perfetto_protos_perfetto_ipc_ipc_gen",
- srcs: [
- "protos/perfetto/ipc/consumer_port.proto",
- "protos/perfetto/ipc/producer_port.proto",
- ],
- tools: [
- "aprotoc",
- "ipc_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/ipc/consumer_port.ipc.cc",
- "external/perfetto/protos/perfetto/ipc/producer_port.ipc.cc",
- ],
+ name: "perfetto_protos_perfetto_ipc_ipc_gen",
+ srcs: [
+ "protos/perfetto/ipc/consumer_port.proto",
+ "protos/perfetto/ipc/producer_port.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "ipc_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/ipc/consumer_port.ipc.cc",
+ "external/perfetto/protos/perfetto/ipc/producer_port.ipc.cc",
+ ],
}
// GN: //protos/perfetto/ipc:ipc
genrule {
- name: "perfetto_protos_perfetto_ipc_ipc_gen_headers",
- srcs: [
- "protos/perfetto/ipc/consumer_port.proto",
- "protos/perfetto/ipc/producer_port.proto",
- ],
- tools: [
- "aprotoc",
- "ipc_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/ipc/consumer_port.ipc.h",
- "external/perfetto/protos/perfetto/ipc/producer_port.ipc.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ srcs: [
+ "protos/perfetto/ipc/consumer_port.proto",
+ "protos/perfetto/ipc/producer_port.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "ipc_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/ipc/consumer_port.ipc.h",
+ "external/perfetto/protos/perfetto/ipc/producer_port.ipc.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/ipc:wire_protocol_cpp
genrule {
- name: "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
- srcs: [
- "protos/perfetto/ipc/wire_protocol.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/ipc/wire_protocol.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+ srcs: [
+ "protos/perfetto/ipc/wire_protocol.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/ipc/wire_protocol.gen.cc",
+ ],
}
// GN: //protos/perfetto/ipc:wire_protocol_cpp
genrule {
- name: "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
- srcs: [
- "protos/perfetto/ipc/wire_protocol.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/ipc/wire_protocol.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/ipc/wire_protocol.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/ipc/wire_protocol.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/metrics/chrome:descriptor
genrule {
- name: "perfetto_protos_perfetto_metrics_chrome_descriptor",
- 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/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",
- "protos/perfetto/metrics/android/lmk_reason_metric.proto",
- "protos/perfetto/metrics/android/mem_metric.proto",
- "protos/perfetto/metrics/android/mem_unagg_metric.proto",
- "protos/perfetto/metrics/android/package_list.proto",
- "protos/perfetto/metrics/android/powrails_metric.proto",
- "protos/perfetto/metrics/android/process_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/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",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --proto_path=external/protobuf/src --descriptor_set_out=$(out) $(in)",
- out: [
- "perfetto_protos_perfetto_metrics_chrome_descriptor.bin",
- ],
+ name: "perfetto_protos_perfetto_metrics_chrome_descriptor",
+ 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/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",
+ "protos/perfetto/metrics/android/lmk_reason_metric.proto",
+ "protos/perfetto/metrics/android/mem_metric.proto",
+ "protos/perfetto/metrics/android/mem_unagg_metric.proto",
+ "protos/perfetto/metrics/android/multiuser_metric.proto",
+ "protos/perfetto/metrics/android/package_list.proto",
+ "protos/perfetto/metrics/android/powrails_metric.proto",
+ "protos/perfetto/metrics/android/process_metadata.proto",
+ "protos/perfetto/metrics/android/profiler_smaps.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/trace_quality.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/chrome/touch_jank.proto",
+ "protos/perfetto/metrics/custom_options.proto",
+ "protos/perfetto/metrics/metrics.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --proto_path=external/protobuf/src --descriptor_set_out=$(out) $(in)",
+ out: [
+ "perfetto_protos_perfetto_metrics_chrome_descriptor.bin",
+ ],
}
// GN: //protos/perfetto/metrics:descriptor
genrule {
- name: "perfetto_protos_perfetto_metrics_descriptor",
- 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/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",
- "protos/perfetto/metrics/android/lmk_reason_metric.proto",
- "protos/perfetto/metrics/android/mem_metric.proto",
- "protos/perfetto/metrics/android/mem_unagg_metric.proto",
- "protos/perfetto/metrics/android/package_list.proto",
- "protos/perfetto/metrics/android/powrails_metric.proto",
- "protos/perfetto/metrics/android/process_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/unsymbolized_frames.proto",
- "protos/perfetto/metrics/metrics.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
- out: [
- "perfetto_protos_perfetto_metrics_descriptor.bin",
- ],
+ name: "perfetto_protos_perfetto_metrics_descriptor",
+ 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/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",
+ "protos/perfetto/metrics/android/lmk_reason_metric.proto",
+ "protos/perfetto/metrics/android/mem_metric.proto",
+ "protos/perfetto/metrics/android/mem_unagg_metric.proto",
+ "protos/perfetto/metrics/android/multiuser_metric.proto",
+ "protos/perfetto/metrics/android/package_list.proto",
+ "protos/perfetto/metrics/android/powrails_metric.proto",
+ "protos/perfetto/metrics/android/process_metadata.proto",
+ "protos/perfetto/metrics/android/profiler_smaps.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/trace_quality.proto",
+ "protos/perfetto/metrics/android/unsymbolized_frames.proto",
+ "protos/perfetto/metrics/metrics.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
+ out: [
+ "perfetto_protos_perfetto_metrics_descriptor.bin",
+ ],
}
// GN: //protos/perfetto/trace/android:cpp
genrule {
- 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",
- "protos/perfetto/trace/android/packages_list.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/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",
- "external/perfetto/protos/perfetto/trace/android/packages_list.gen.cc",
- ],
+ 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",
+ "protos/perfetto/trace/android/packages_list.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/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",
+ "external/perfetto/protos/perfetto/trace/android/packages_list.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/android:cpp
genrule {
- 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",
- "protos/perfetto/trace/android/packages_list.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/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",
- "external/perfetto/protos/perfetto/trace/android/packages_list.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "protos/perfetto/trace/android/packages_list.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/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",
+ "external/perfetto/protos/perfetto/trace/android/packages_list.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/android:lite
genrule {
- 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",
- "protos/perfetto/trace/android/packages_list.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/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",
- "external/perfetto/protos/perfetto/trace/android/packages_list.pb.cc",
- ],
+ 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",
+ "protos/perfetto/trace/android/packages_list.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/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",
+ "external/perfetto/protos/perfetto/trace/android/packages_list.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/android:lite
genrule {
- 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",
- "protos/perfetto/trace/android/packages_list.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/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",
- "external/perfetto/protos/perfetto/trace/android/packages_list.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "protos/perfetto/trace/android/packages_list.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/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",
+ "external/perfetto/protos/perfetto/trace/android/packages_list.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/android:zero
genrule {
- 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",
- "protos/perfetto/trace/android/packages_list.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/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",
- "external/perfetto/protos/perfetto/trace/android/packages_list.pbzero.cc",
- ],
+ 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",
+ "protos/perfetto/trace/android/packages_list.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/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",
+ "external/perfetto/protos/perfetto/trace/android/packages_list.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/android:zero
genrule {
- 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",
- "protos/perfetto/trace/android/packages_list.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/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",
- "external/perfetto/protos/perfetto/trace/android/packages_list.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "protos/perfetto/trace/android/packages_list.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/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",
+ "external/perfetto/protos/perfetto/trace/android/packages_list.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/chrome:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_chrome_cpp_gen",
- srcs: [
- "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_trace_event.proto",
- ],
- tools: [
- "aprotoc",
- "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/trace/chrome/chrome_benchmark_metadata.gen.cc",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.gen.cc",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_chrome_cpp_gen",
+ srcs: [
+ "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_trace_event.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "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/trace/chrome/chrome_benchmark_metadata.gen.cc",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.gen.cc",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/chrome:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
- srcs: [
- "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_trace_event.proto",
- ],
- tools: [
- "aprotoc",
- "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/trace/chrome/chrome_benchmark_metadata.gen.h",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.gen.h",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_trace_event.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "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/trace/chrome/chrome_benchmark_metadata.gen.h",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.gen.h",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/chrome:lite
genrule {
- name: "perfetto_protos_perfetto_trace_chrome_lite_gen",
- srcs: [
- "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_trace_event.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pb.cc",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pb.cc",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_chrome_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_trace_event.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pb.cc",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pb.cc",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/chrome:lite
genrule {
- name: "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
- srcs: [
- "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_trace_event.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pb.h",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pb.h",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_trace_event.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pb.h",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pb.h",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/chrome:zero
genrule {
- name: "perfetto_protos_perfetto_trace_chrome_zero_gen",
- srcs: [
- "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_trace_event.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- 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/chrome/chrome_benchmark_metadata.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_chrome_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_trace_event.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ 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/chrome/chrome_benchmark_metadata.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/chrome:zero
genrule {
- name: "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_trace_event.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- 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/chrome/chrome_benchmark_metadata.pbzero.h",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.h",
- "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_trace_event.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ 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/chrome/chrome_benchmark_metadata.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace:descriptor
genrule {
- name: "perfetto_protos_perfetto_trace_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",
- "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",
- "protos/perfetto/trace/android/packages_list.proto",
- "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_metadata.proto",
- "protos/perfetto/trace/chrome/chrome_trace_event.proto",
- "protos/perfetto/trace/clock_snapshot.proto",
- "protos/perfetto/trace/extension_descriptor.proto",
- "protos/perfetto/trace/filesystem/inode_file_map.proto",
- "protos/perfetto/trace/ftrace/binder.proto",
- "protos/perfetto/trace/ftrace/block.proto",
- "protos/perfetto/trace/ftrace/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",
- "protos/perfetto/trace/ftrace/ion.proto",
- "protos/perfetto/trace/ftrace/ipi.proto",
- "protos/perfetto/trace/ftrace/irq.proto",
- "protos/perfetto/trace/ftrace/kmem.proto",
- "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
- "protos/perfetto/trace/ftrace/mali.proto",
- "protos/perfetto/trace/ftrace/mdss.proto",
- "protos/perfetto/trace/ftrace/mm_event.proto",
- "protos/perfetto/trace/ftrace/oom.proto",
- "protos/perfetto/trace/ftrace/power.proto",
- "protos/perfetto/trace/ftrace/raw_syscalls.proto",
- "protos/perfetto/trace/ftrace/regulator.proto",
- "protos/perfetto/trace/ftrace/sched.proto",
- "protos/perfetto/trace/ftrace/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",
- "protos/perfetto/trace/gpu/gpu_counter_event.proto",
- "protos/perfetto/trace/gpu/gpu_log.proto",
- "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
- "protos/perfetto/trace/gpu/vulkan_api_event.proto",
- "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
- "protos/perfetto/trace/interned_data/interned_data.proto",
- "protos/perfetto/trace/memory_graph.proto",
- "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
- "protos/perfetto/trace/perfetto/tracing_service_event.proto",
- "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto",
- "protos/perfetto/trace/power/battery_counters.proto",
- "protos/perfetto/trace/power/power_rails.proto",
- "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",
- "protos/perfetto/trace/profiling/smaps.proto",
- "protos/perfetto/trace/ps/process_stats.proto",
- "protos/perfetto/trace/ps/process_tree.proto",
- "protos/perfetto/trace/sys_stats/sys_stats.proto",
- "protos/perfetto/trace/system_info.proto",
- "protos/perfetto/trace/system_info/cpu_info.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/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/perfetto/trace/trigger.proto",
- "protos/perfetto/trace/ui_state.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_descriptor.bin",
- ],
+ name: "perfetto_protos_perfetto_trace_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",
+ "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",
+ "protos/perfetto/trace/android/packages_list.proto",
+ "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_trace_event.proto",
+ "protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/extension_descriptor.proto",
+ "protos/perfetto/trace/filesystem/inode_file_map.proto",
+ "protos/perfetto/trace/ftrace/binder.proto",
+ "protos/perfetto/trace/ftrace/block.proto",
+ "protos/perfetto/trace/ftrace/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",
+ "protos/perfetto/trace/ftrace/ion.proto",
+ "protos/perfetto/trace/ftrace/ipi.proto",
+ "protos/perfetto/trace/ftrace/irq.proto",
+ "protos/perfetto/trace/ftrace/kmem.proto",
+ "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
+ "protos/perfetto/trace/ftrace/mali.proto",
+ "protos/perfetto/trace/ftrace/mdss.proto",
+ "protos/perfetto/trace/ftrace/mm_event.proto",
+ "protos/perfetto/trace/ftrace/oom.proto",
+ "protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/raw_syscalls.proto",
+ "protos/perfetto/trace/ftrace/regulator.proto",
+ "protos/perfetto/trace/ftrace/sched.proto",
+ "protos/perfetto/trace/ftrace/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",
+ "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+ "protos/perfetto/trace/gpu/gpu_log.proto",
+ "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_api_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
+ "protos/perfetto/trace/interned_data/interned_data.proto",
+ "protos/perfetto/trace/memory_graph.proto",
+ "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
+ "protos/perfetto/trace/perfetto/tracing_service_event.proto",
+ "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto",
+ "protos/perfetto/trace/power/battery_counters.proto",
+ "protos/perfetto/trace/power/power_rails.proto",
+ "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",
+ "protos/perfetto/trace/profiling/smaps.proto",
+ "protos/perfetto/trace/ps/process_stats.proto",
+ "protos/perfetto/trace/ps/process_tree.proto",
+ "protos/perfetto/trace/sys_stats/sys_stats.proto",
+ "protos/perfetto/trace/system_info.proto",
+ "protos/perfetto/trace/system_info/cpu_info.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/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/perfetto/trace/trigger.proto",
+ "protos/perfetto/trace/ui_state.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_descriptor.bin",
+ ],
}
// GN: //protos/perfetto/trace/filesystem:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_filesystem_cpp_gen",
- srcs: [
- "protos/perfetto/trace/filesystem/inode_file_map.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/trace/filesystem/inode_file_map.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_filesystem_cpp_gen",
+ srcs: [
+ "protos/perfetto/trace/filesystem/inode_file_map.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/trace/filesystem/inode_file_map.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/filesystem:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
- srcs: [
- "protos/perfetto/trace/filesystem/inode_file_map.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/trace/filesystem/inode_file_map.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/filesystem/inode_file_map.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/trace/filesystem/inode_file_map.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/filesystem:lite
genrule {
- name: "perfetto_protos_perfetto_trace_filesystem_lite_gen",
- srcs: [
- "protos/perfetto/trace/filesystem/inode_file_map.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/filesystem/inode_file_map.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_filesystem_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/filesystem/inode_file_map.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/filesystem/inode_file_map.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/filesystem:lite
genrule {
- name: "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
- srcs: [
- "protos/perfetto/trace/filesystem/inode_file_map.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/filesystem/inode_file_map.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/filesystem/inode_file_map.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/filesystem/inode_file_map.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/filesystem:zero
genrule {
- name: "perfetto_protos_perfetto_trace_filesystem_zero_gen",
- srcs: [
- "protos/perfetto/trace/filesystem/inode_file_map.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/filesystem/inode_file_map.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_filesystem_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/filesystem/inode_file_map.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/filesystem/inode_file_map.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/filesystem:zero
genrule {
- name: "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace/filesystem/inode_file_map.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/filesystem/inode_file_map.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/filesystem/inode_file_map.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/filesystem/inode_file_map.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/ftrace:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_ftrace_cpp_gen",
- srcs: [
- "protos/perfetto/trace/ftrace/binder.proto",
- "protos/perfetto/trace/ftrace/block.proto",
- "protos/perfetto/trace/ftrace/cgroup.proto",
- "protos/perfetto/trace/ftrace/clk.proto",
- "protos/perfetto/trace/ftrace/compaction.proto",
- "protos/perfetto/trace/ftrace/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",
- "protos/perfetto/trace/ftrace/ion.proto",
- "protos/perfetto/trace/ftrace/ipi.proto",
- "protos/perfetto/trace/ftrace/irq.proto",
- "protos/perfetto/trace/ftrace/kmem.proto",
- "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
- "protos/perfetto/trace/ftrace/mali.proto",
- "protos/perfetto/trace/ftrace/mdss.proto",
- "protos/perfetto/trace/ftrace/mm_event.proto",
- "protos/perfetto/trace/ftrace/oom.proto",
- "protos/perfetto/trace/ftrace/power.proto",
- "protos/perfetto/trace/ftrace/raw_syscalls.proto",
- "protos/perfetto/trace/ftrace/regulator.proto",
- "protos/perfetto/trace/ftrace/sched.proto",
- "protos/perfetto/trace/ftrace/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",
- ],
- 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/trace/ftrace/binder.gen.cc",
- "external/perfetto/protos/perfetto/trace/ftrace/block.gen.cc",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/ion.gen.cc",
- "external/perfetto/protos/perfetto/trace/ftrace/ipi.gen.cc",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/power.gen.cc",
- "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",
- ],
+ name: "perfetto_protos_perfetto_trace_ftrace_cpp_gen",
+ srcs: [
+ "protos/perfetto/trace/ftrace/binder.proto",
+ "protos/perfetto/trace/ftrace/block.proto",
+ "protos/perfetto/trace/ftrace/cgroup.proto",
+ "protos/perfetto/trace/ftrace/clk.proto",
+ "protos/perfetto/trace/ftrace/compaction.proto",
+ "protos/perfetto/trace/ftrace/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",
+ "protos/perfetto/trace/ftrace/ion.proto",
+ "protos/perfetto/trace/ftrace/ipi.proto",
+ "protos/perfetto/trace/ftrace/irq.proto",
+ "protos/perfetto/trace/ftrace/kmem.proto",
+ "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
+ "protos/perfetto/trace/ftrace/mali.proto",
+ "protos/perfetto/trace/ftrace/mdss.proto",
+ "protos/perfetto/trace/ftrace/mm_event.proto",
+ "protos/perfetto/trace/ftrace/oom.proto",
+ "protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/raw_syscalls.proto",
+ "protos/perfetto/trace/ftrace/regulator.proto",
+ "protos/perfetto/trace/ftrace/sched.proto",
+ "protos/perfetto/trace/ftrace/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",
+ ],
+ 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/trace/ftrace/binder.gen.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/block.gen.cc",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/ion.gen.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/ipi.gen.cc",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/power.gen.cc",
+ "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",
+ ],
}
// GN: //protos/perfetto/trace/ftrace:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
- srcs: [
- "protos/perfetto/trace/ftrace/binder.proto",
- "protos/perfetto/trace/ftrace/block.proto",
- "protos/perfetto/trace/ftrace/cgroup.proto",
- "protos/perfetto/trace/ftrace/clk.proto",
- "protos/perfetto/trace/ftrace/compaction.proto",
- "protos/perfetto/trace/ftrace/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",
- "protos/perfetto/trace/ftrace/ion.proto",
- "protos/perfetto/trace/ftrace/ipi.proto",
- "protos/perfetto/trace/ftrace/irq.proto",
- "protos/perfetto/trace/ftrace/kmem.proto",
- "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
- "protos/perfetto/trace/ftrace/mali.proto",
- "protos/perfetto/trace/ftrace/mdss.proto",
- "protos/perfetto/trace/ftrace/mm_event.proto",
- "protos/perfetto/trace/ftrace/oom.proto",
- "protos/perfetto/trace/ftrace/power.proto",
- "protos/perfetto/trace/ftrace/raw_syscalls.proto",
- "protos/perfetto/trace/ftrace/regulator.proto",
- "protos/perfetto/trace/ftrace/sched.proto",
- "protos/perfetto/trace/ftrace/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",
- ],
- 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/trace/ftrace/binder.gen.h",
- "external/perfetto/protos/perfetto/trace/ftrace/block.gen.h",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/ion.gen.h",
- "external/perfetto/protos/perfetto/trace/ftrace/ipi.gen.h",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/power.gen.h",
- "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",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/ftrace/binder.proto",
+ "protos/perfetto/trace/ftrace/block.proto",
+ "protos/perfetto/trace/ftrace/cgroup.proto",
+ "protos/perfetto/trace/ftrace/clk.proto",
+ "protos/perfetto/trace/ftrace/compaction.proto",
+ "protos/perfetto/trace/ftrace/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",
+ "protos/perfetto/trace/ftrace/ion.proto",
+ "protos/perfetto/trace/ftrace/ipi.proto",
+ "protos/perfetto/trace/ftrace/irq.proto",
+ "protos/perfetto/trace/ftrace/kmem.proto",
+ "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
+ "protos/perfetto/trace/ftrace/mali.proto",
+ "protos/perfetto/trace/ftrace/mdss.proto",
+ "protos/perfetto/trace/ftrace/mm_event.proto",
+ "protos/perfetto/trace/ftrace/oom.proto",
+ "protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/raw_syscalls.proto",
+ "protos/perfetto/trace/ftrace/regulator.proto",
+ "protos/perfetto/trace/ftrace/sched.proto",
+ "protos/perfetto/trace/ftrace/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",
+ ],
+ 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/trace/ftrace/binder.gen.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/block.gen.h",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/ion.gen.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/ipi.gen.h",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/power.gen.h",
+ "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",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/ftrace:lite
genrule {
- name: "perfetto_protos_perfetto_trace_ftrace_lite_gen",
- srcs: [
- "protos/perfetto/trace/ftrace/binder.proto",
- "protos/perfetto/trace/ftrace/block.proto",
- "protos/perfetto/trace/ftrace/cgroup.proto",
- "protos/perfetto/trace/ftrace/clk.proto",
- "protos/perfetto/trace/ftrace/compaction.proto",
- "protos/perfetto/trace/ftrace/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",
- "protos/perfetto/trace/ftrace/ion.proto",
- "protos/perfetto/trace/ftrace/ipi.proto",
- "protos/perfetto/trace/ftrace/irq.proto",
- "protos/perfetto/trace/ftrace/kmem.proto",
- "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
- "protos/perfetto/trace/ftrace/mali.proto",
- "protos/perfetto/trace/ftrace/mdss.proto",
- "protos/perfetto/trace/ftrace/mm_event.proto",
- "protos/perfetto/trace/ftrace/oom.proto",
- "protos/perfetto/trace/ftrace/power.proto",
- "protos/perfetto/trace/ftrace/raw_syscalls.proto",
- "protos/perfetto/trace/ftrace/regulator.proto",
- "protos/perfetto/trace/ftrace/sched.proto",
- "protos/perfetto/trace/ftrace/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",
- ],
- 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/ftrace/binder.pb.cc",
- "external/perfetto/protos/perfetto/trace/ftrace/block.pb.cc",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/ion.pb.cc",
- "external/perfetto/protos/perfetto/trace/ftrace/ipi.pb.cc",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/power.pb.cc",
- "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",
- ],
+ name: "perfetto_protos_perfetto_trace_ftrace_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/ftrace/binder.proto",
+ "protos/perfetto/trace/ftrace/block.proto",
+ "protos/perfetto/trace/ftrace/cgroup.proto",
+ "protos/perfetto/trace/ftrace/clk.proto",
+ "protos/perfetto/trace/ftrace/compaction.proto",
+ "protos/perfetto/trace/ftrace/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",
+ "protos/perfetto/trace/ftrace/ion.proto",
+ "protos/perfetto/trace/ftrace/ipi.proto",
+ "protos/perfetto/trace/ftrace/irq.proto",
+ "protos/perfetto/trace/ftrace/kmem.proto",
+ "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
+ "protos/perfetto/trace/ftrace/mali.proto",
+ "protos/perfetto/trace/ftrace/mdss.proto",
+ "protos/perfetto/trace/ftrace/mm_event.proto",
+ "protos/perfetto/trace/ftrace/oom.proto",
+ "protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/raw_syscalls.proto",
+ "protos/perfetto/trace/ftrace/regulator.proto",
+ "protos/perfetto/trace/ftrace/sched.proto",
+ "protos/perfetto/trace/ftrace/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",
+ ],
+ 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/ftrace/binder.pb.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/block.pb.cc",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/ion.pb.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/ipi.pb.cc",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/power.pb.cc",
+ "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",
+ ],
}
// GN: //protos/perfetto/trace/ftrace:lite
genrule {
- name: "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
- srcs: [
- "protos/perfetto/trace/ftrace/binder.proto",
- "protos/perfetto/trace/ftrace/block.proto",
- "protos/perfetto/trace/ftrace/cgroup.proto",
- "protos/perfetto/trace/ftrace/clk.proto",
- "protos/perfetto/trace/ftrace/compaction.proto",
- "protos/perfetto/trace/ftrace/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",
- "protos/perfetto/trace/ftrace/ion.proto",
- "protos/perfetto/trace/ftrace/ipi.proto",
- "protos/perfetto/trace/ftrace/irq.proto",
- "protos/perfetto/trace/ftrace/kmem.proto",
- "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
- "protos/perfetto/trace/ftrace/mali.proto",
- "protos/perfetto/trace/ftrace/mdss.proto",
- "protos/perfetto/trace/ftrace/mm_event.proto",
- "protos/perfetto/trace/ftrace/oom.proto",
- "protos/perfetto/trace/ftrace/power.proto",
- "protos/perfetto/trace/ftrace/raw_syscalls.proto",
- "protos/perfetto/trace/ftrace/regulator.proto",
- "protos/perfetto/trace/ftrace/sched.proto",
- "protos/perfetto/trace/ftrace/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",
- ],
- 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/ftrace/binder.pb.h",
- "external/perfetto/protos/perfetto/trace/ftrace/block.pb.h",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/ion.pb.h",
- "external/perfetto/protos/perfetto/trace/ftrace/ipi.pb.h",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/power.pb.h",
- "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",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/ftrace/binder.proto",
+ "protos/perfetto/trace/ftrace/block.proto",
+ "protos/perfetto/trace/ftrace/cgroup.proto",
+ "protos/perfetto/trace/ftrace/clk.proto",
+ "protos/perfetto/trace/ftrace/compaction.proto",
+ "protos/perfetto/trace/ftrace/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",
+ "protos/perfetto/trace/ftrace/ion.proto",
+ "protos/perfetto/trace/ftrace/ipi.proto",
+ "protos/perfetto/trace/ftrace/irq.proto",
+ "protos/perfetto/trace/ftrace/kmem.proto",
+ "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
+ "protos/perfetto/trace/ftrace/mali.proto",
+ "protos/perfetto/trace/ftrace/mdss.proto",
+ "protos/perfetto/trace/ftrace/mm_event.proto",
+ "protos/perfetto/trace/ftrace/oom.proto",
+ "protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/raw_syscalls.proto",
+ "protos/perfetto/trace/ftrace/regulator.proto",
+ "protos/perfetto/trace/ftrace/sched.proto",
+ "protos/perfetto/trace/ftrace/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",
+ ],
+ 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/ftrace/binder.pb.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/block.pb.h",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/ion.pb.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/ipi.pb.h",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/power.pb.h",
+ "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",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/ftrace:zero
genrule {
- name: "perfetto_protos_perfetto_trace_ftrace_zero_gen",
- srcs: [
- "protos/perfetto/trace/ftrace/binder.proto",
- "protos/perfetto/trace/ftrace/block.proto",
- "protos/perfetto/trace/ftrace/cgroup.proto",
- "protos/perfetto/trace/ftrace/clk.proto",
- "protos/perfetto/trace/ftrace/compaction.proto",
- "protos/perfetto/trace/ftrace/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",
- "protos/perfetto/trace/ftrace/ion.proto",
- "protos/perfetto/trace/ftrace/ipi.proto",
- "protos/perfetto/trace/ftrace/irq.proto",
- "protos/perfetto/trace/ftrace/kmem.proto",
- "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
- "protos/perfetto/trace/ftrace/mali.proto",
- "protos/perfetto/trace/ftrace/mdss.proto",
- "protos/perfetto/trace/ftrace/mm_event.proto",
- "protos/perfetto/trace/ftrace/oom.proto",
- "protos/perfetto/trace/ftrace/power.proto",
- "protos/perfetto/trace/ftrace/raw_syscalls.proto",
- "protos/perfetto/trace/ftrace/regulator.proto",
- "protos/perfetto/trace/ftrace/sched.proto",
- "protos/perfetto/trace/ftrace/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",
- ],
- 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/ftrace/binder.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/ftrace/block.pbzero.cc",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/ion.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/ftrace/ipi.pbzero.cc",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/power.pbzero.cc",
- "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",
- ],
+ name: "perfetto_protos_perfetto_trace_ftrace_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/ftrace/binder.proto",
+ "protos/perfetto/trace/ftrace/block.proto",
+ "protos/perfetto/trace/ftrace/cgroup.proto",
+ "protos/perfetto/trace/ftrace/clk.proto",
+ "protos/perfetto/trace/ftrace/compaction.proto",
+ "protos/perfetto/trace/ftrace/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",
+ "protos/perfetto/trace/ftrace/ion.proto",
+ "protos/perfetto/trace/ftrace/ipi.proto",
+ "protos/perfetto/trace/ftrace/irq.proto",
+ "protos/perfetto/trace/ftrace/kmem.proto",
+ "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
+ "protos/perfetto/trace/ftrace/mali.proto",
+ "protos/perfetto/trace/ftrace/mdss.proto",
+ "protos/perfetto/trace/ftrace/mm_event.proto",
+ "protos/perfetto/trace/ftrace/oom.proto",
+ "protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/raw_syscalls.proto",
+ "protos/perfetto/trace/ftrace/regulator.proto",
+ "protos/perfetto/trace/ftrace/sched.proto",
+ "protos/perfetto/trace/ftrace/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",
+ ],
+ 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/ftrace/binder.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/block.pbzero.cc",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/ion.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/ipi.pbzero.cc",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/power.pbzero.cc",
+ "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",
+ ],
}
// GN: //protos/perfetto/trace/ftrace:zero
genrule {
- name: "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace/ftrace/binder.proto",
- "protos/perfetto/trace/ftrace/block.proto",
- "protos/perfetto/trace/ftrace/cgroup.proto",
- "protos/perfetto/trace/ftrace/clk.proto",
- "protos/perfetto/trace/ftrace/compaction.proto",
- "protos/perfetto/trace/ftrace/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",
- "protos/perfetto/trace/ftrace/ion.proto",
- "protos/perfetto/trace/ftrace/ipi.proto",
- "protos/perfetto/trace/ftrace/irq.proto",
- "protos/perfetto/trace/ftrace/kmem.proto",
- "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
- "protos/perfetto/trace/ftrace/mali.proto",
- "protos/perfetto/trace/ftrace/mdss.proto",
- "protos/perfetto/trace/ftrace/mm_event.proto",
- "protos/perfetto/trace/ftrace/oom.proto",
- "protos/perfetto/trace/ftrace/power.proto",
- "protos/perfetto/trace/ftrace/raw_syscalls.proto",
- "protos/perfetto/trace/ftrace/regulator.proto",
- "protos/perfetto/trace/ftrace/sched.proto",
- "protos/perfetto/trace/ftrace/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",
- ],
- 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/ftrace/binder.pbzero.h",
- "external/perfetto/protos/perfetto/trace/ftrace/block.pbzero.h",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/ion.pbzero.h",
- "external/perfetto/protos/perfetto/trace/ftrace/ipi.pbzero.h",
- "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",
- "external/perfetto/protos/perfetto/trace/ftrace/power.pbzero.h",
- "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",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/ftrace/binder.proto",
+ "protos/perfetto/trace/ftrace/block.proto",
+ "protos/perfetto/trace/ftrace/cgroup.proto",
+ "protos/perfetto/trace/ftrace/clk.proto",
+ "protos/perfetto/trace/ftrace/compaction.proto",
+ "protos/perfetto/trace/ftrace/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",
+ "protos/perfetto/trace/ftrace/ion.proto",
+ "protos/perfetto/trace/ftrace/ipi.proto",
+ "protos/perfetto/trace/ftrace/irq.proto",
+ "protos/perfetto/trace/ftrace/kmem.proto",
+ "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
+ "protos/perfetto/trace/ftrace/mali.proto",
+ "protos/perfetto/trace/ftrace/mdss.proto",
+ "protos/perfetto/trace/ftrace/mm_event.proto",
+ "protos/perfetto/trace/ftrace/oom.proto",
+ "protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/raw_syscalls.proto",
+ "protos/perfetto/trace/ftrace/regulator.proto",
+ "protos/perfetto/trace/ftrace/sched.proto",
+ "protos/perfetto/trace/ftrace/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",
+ ],
+ 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/ftrace/binder.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/block.pbzero.h",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/ion.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/ipi.pbzero.h",
+ "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",
+ "external/perfetto/protos/perfetto/trace/ftrace/power.pbzero.h",
+ "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",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/gpu:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_gpu_cpp_gen",
- srcs: [
- "protos/perfetto/trace/gpu/gpu_counter_event.proto",
- "protos/perfetto/trace/gpu/gpu_log.proto",
- "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
- "protos/perfetto/trace/gpu/vulkan_api_event.proto",
- "protos/perfetto/trace/gpu/vulkan_memory_event.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/trace/gpu/gpu_counter_event.gen.cc",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_log.gen.cc",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.gen.cc",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.gen.cc",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_gpu_cpp_gen",
+ srcs: [
+ "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+ "protos/perfetto/trace/gpu/gpu_log.proto",
+ "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_api_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_memory_event.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/trace/gpu/gpu_counter_event.gen.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_log.gen.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.gen.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.gen.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/gpu:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_gpu_cpp_gen_headers",
- srcs: [
- "protos/perfetto/trace/gpu/gpu_counter_event.proto",
- "protos/perfetto/trace/gpu/gpu_log.proto",
- "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
- "protos/perfetto/trace/gpu/vulkan_api_event.proto",
- "protos/perfetto/trace/gpu/vulkan_memory_event.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/trace/gpu/gpu_counter_event.gen.h",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_log.gen.h",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.gen.h",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.gen.h",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_gpu_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+ "protos/perfetto/trace/gpu/gpu_log.proto",
+ "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_api_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_memory_event.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/trace/gpu/gpu_counter_event.gen.h",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_log.gen.h",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.gen.h",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.gen.h",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/gpu:lite
genrule {
- name: "perfetto_protos_perfetto_trace_gpu_lite_gen",
- srcs: [
- "protos/perfetto/trace/gpu/gpu_counter_event.proto",
- "protos/perfetto/trace/gpu/gpu_log.proto",
- "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
- "protos/perfetto/trace/gpu/vulkan_api_event.proto",
- "protos/perfetto/trace/gpu/vulkan_memory_event.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/gpu/gpu_counter_event.pb.cc",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.cc",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pb.cc",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pb.cc",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_gpu_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+ "protos/perfetto/trace/gpu/gpu_log.proto",
+ "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_api_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_memory_event.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/gpu/gpu_counter_event.pb.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pb.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pb.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/gpu:lite
genrule {
- name: "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
- srcs: [
- "protos/perfetto/trace/gpu/gpu_counter_event.proto",
- "protos/perfetto/trace/gpu/gpu_log.proto",
- "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
- "protos/perfetto/trace/gpu/vulkan_api_event.proto",
- "protos/perfetto/trace/gpu/vulkan_memory_event.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/gpu/gpu_counter_event.pb.h",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.h",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pb.h",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pb.h",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+ "protos/perfetto/trace/gpu/gpu_log.proto",
+ "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_api_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_memory_event.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/gpu/gpu_counter_event.pb.h",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.h",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pb.h",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pb.h",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/gpu:zero
genrule {
- name: "perfetto_protos_perfetto_trace_gpu_zero_gen",
- srcs: [
- "protos/perfetto/trace/gpu/gpu_counter_event.proto",
- "protos/perfetto/trace/gpu/gpu_log.proto",
- "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
- "protos/perfetto/trace/gpu/vulkan_api_event.proto",
- "protos/perfetto/trace/gpu/vulkan_memory_event.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/gpu/gpu_counter_event.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_gpu_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+ "protos/perfetto/trace/gpu/gpu_log.proto",
+ "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_api_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_memory_event.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/gpu/gpu_counter_event.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/gpu:zero
genrule {
- name: "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace/gpu/gpu_counter_event.proto",
- "protos/perfetto/trace/gpu/gpu_log.proto",
- "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
- "protos/perfetto/trace/gpu/vulkan_api_event.proto",
- "protos/perfetto/trace/gpu/vulkan_memory_event.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/gpu/gpu_counter_event.pbzero.h",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pbzero.h",
- "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pbzero.h",
- "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+ "protos/perfetto/trace/gpu/gpu_log.proto",
+ "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_api_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_memory_event.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/gpu/gpu_counter_event.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/interned_data:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_interned_data_cpp_gen",
- srcs: [
- "protos/perfetto/trace/interned_data/interned_data.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/trace/interned_data/interned_data.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_interned_data_cpp_gen",
+ srcs: [
+ "protos/perfetto/trace/interned_data/interned_data.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/trace/interned_data/interned_data.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/interned_data:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_interned_data_cpp_gen_headers",
- srcs: [
- "protos/perfetto/trace/interned_data/interned_data.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/trace/interned_data/interned_data.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_interned_data_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/interned_data/interned_data.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/trace/interned_data/interned_data.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/interned_data:lite
genrule {
- name: "perfetto_protos_perfetto_trace_interned_data_lite_gen",
- srcs: [
- "protos/perfetto/trace/interned_data/interned_data.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/interned_data/interned_data.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_interned_data_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/interned_data/interned_data.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/interned_data/interned_data.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/interned_data:lite
genrule {
- name: "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
- srcs: [
- "protos/perfetto/trace/interned_data/interned_data.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/interned_data/interned_data.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/interned_data/interned_data.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/interned_data/interned_data.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/interned_data:zero
genrule {
- name: "perfetto_protos_perfetto_trace_interned_data_zero_gen",
- srcs: [
- "protos/perfetto/trace/interned_data/interned_data.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/interned_data/interned_data.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_interned_data_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/interned_data/interned_data.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/interned_data/interned_data.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/interned_data:zero
genrule {
- name: "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace/interned_data/interned_data.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/interned_data/interned_data.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/interned_data/interned_data.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/interned_data/interned_data.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace:minimal_cpp
genrule {
- name: "perfetto_protos_perfetto_trace_minimal_cpp_gen",
- srcs: [
- "protos/perfetto/trace/clock_snapshot.proto",
- "protos/perfetto/trace/system_info.proto",
- "protos/perfetto/trace/trigger.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/trace/clock_snapshot.gen.cc",
- "external/perfetto/protos/perfetto/trace/system_info.gen.cc",
- "external/perfetto/protos/perfetto/trace/trigger.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_minimal_cpp_gen",
+ srcs: [
+ "protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/system_info.proto",
+ "protos/perfetto/trace/trigger.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/trace/clock_snapshot.gen.cc",
+ "external/perfetto/protos/perfetto/trace/system_info.gen.cc",
+ "external/perfetto/protos/perfetto/trace/trigger.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace:minimal_cpp
genrule {
- name: "perfetto_protos_perfetto_trace_minimal_cpp_gen_headers",
- srcs: [
- "protos/perfetto/trace/clock_snapshot.proto",
- "protos/perfetto/trace/system_info.proto",
- "protos/perfetto/trace/trigger.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/trace/clock_snapshot.gen.h",
- "external/perfetto/protos/perfetto/trace/system_info.gen.h",
- "external/perfetto/protos/perfetto/trace/trigger.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_minimal_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/system_info.proto",
+ "protos/perfetto/trace/trigger.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/trace/clock_snapshot.gen.h",
+ "external/perfetto/protos/perfetto/trace/system_info.gen.h",
+ "external/perfetto/protos/perfetto/trace/trigger.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace:minimal_lite
genrule {
- name: "perfetto_protos_perfetto_trace_minimal_lite_gen",
- srcs: [
- "protos/perfetto/trace/clock_snapshot.proto",
- "protos/perfetto/trace/system_info.proto",
- "protos/perfetto/trace/trigger.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/clock_snapshot.pb.cc",
- "external/perfetto/protos/perfetto/trace/system_info.pb.cc",
- "external/perfetto/protos/perfetto/trace/trigger.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_minimal_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/system_info.proto",
+ "protos/perfetto/trace/trigger.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/clock_snapshot.pb.cc",
+ "external/perfetto/protos/perfetto/trace/system_info.pb.cc",
+ "external/perfetto/protos/perfetto/trace/trigger.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace:minimal_lite
genrule {
- name: "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
- srcs: [
- "protos/perfetto/trace/clock_snapshot.proto",
- "protos/perfetto/trace/system_info.proto",
- "protos/perfetto/trace/trigger.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/clock_snapshot.pb.h",
- "external/perfetto/protos/perfetto/trace/system_info.pb.h",
- "external/perfetto/protos/perfetto/trace/trigger.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/system_info.proto",
+ "protos/perfetto/trace/trigger.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/clock_snapshot.pb.h",
+ "external/perfetto/protos/perfetto/trace/system_info.pb.h",
+ "external/perfetto/protos/perfetto/trace/trigger.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace:minimal_zero
genrule {
- name: "perfetto_protos_perfetto_trace_minimal_zero_gen",
- srcs: [
- "protos/perfetto/trace/clock_snapshot.proto",
- "protos/perfetto/trace/system_info.proto",
- "protos/perfetto/trace/trigger.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/system_info.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/trigger.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_minimal_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/system_info.proto",
+ "protos/perfetto/trace/trigger.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/system_info.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/trigger.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace:minimal_zero
genrule {
- name: "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace/clock_snapshot.proto",
- "protos/perfetto/trace/system_info.proto",
- "protos/perfetto/trace/trigger.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.h",
- "external/perfetto/protos/perfetto/trace/system_info.pbzero.h",
- "external/perfetto/protos/perfetto/trace/trigger.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/system_info.proto",
+ "protos/perfetto/trace/trigger.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/system_info.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/trigger.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace:non_minimal_cpp
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",
- "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/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",
- ],
+ 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",
+ "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/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",
+ ],
}
// GN: //protos/perfetto/trace:non_minimal_cpp
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",
- "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/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: [
- ".",
- "protos",
- ],
+ 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",
+ "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/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: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace:non_minimal_lite
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",
- ],
+ 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",
+ ],
}
// GN: //protos/perfetto/trace:non_minimal_lite
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: [
- ".",
- "protos",
- ],
+ 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: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace:non_minimal_zero
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",
- "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/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",
- ],
+ 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",
+ "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/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",
+ ],
}
// GN: //protos/perfetto/trace:non_minimal_zero
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",
- "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/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: [
- ".",
- "protos",
- ],
+ 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",
+ "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/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: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/perfetto:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_perfetto_cpp_gen",
- srcs: [
- "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
- "protos/perfetto/trace/perfetto/tracing_service_event.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/trace/perfetto/perfetto_metatrace.gen.cc",
- "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_perfetto_cpp_gen",
+ srcs: [
+ "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
+ "protos/perfetto/trace/perfetto/tracing_service_event.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/trace/perfetto/perfetto_metatrace.gen.cc",
+ "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/perfetto:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
- srcs: [
- "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
- "protos/perfetto/trace/perfetto/tracing_service_event.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/trace/perfetto/perfetto_metatrace.gen.h",
- "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
+ "protos/perfetto/trace/perfetto/tracing_service_event.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/trace/perfetto/perfetto_metatrace.gen.h",
+ "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/perfetto:lite
genrule {
- name: "perfetto_protos_perfetto_trace_perfetto_lite_gen",
- srcs: [
- "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
- "protos/perfetto/trace/perfetto/tracing_service_event.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/perfetto/perfetto_metatrace.pb.cc",
- "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_perfetto_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
+ "protos/perfetto/trace/perfetto/tracing_service_event.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/perfetto/perfetto_metatrace.pb.cc",
+ "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/perfetto:lite
genrule {
- name: "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
- srcs: [
- "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
- "protos/perfetto/trace/perfetto/tracing_service_event.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/perfetto/perfetto_metatrace.pb.h",
- "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
+ "protos/perfetto/trace/perfetto/tracing_service_event.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/perfetto/perfetto_metatrace.pb.h",
+ "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/perfetto:zero
genrule {
- name: "perfetto_protos_perfetto_trace_perfetto_zero_gen",
- srcs: [
- "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
- "protos/perfetto/trace/perfetto/tracing_service_event.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/perfetto/perfetto_metatrace.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_perfetto_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
+ "protos/perfetto/trace/perfetto/tracing_service_event.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/perfetto/perfetto_metatrace.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/perfetto:zero
genrule {
- name: "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
- "protos/perfetto/trace/perfetto/tracing_service_event.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/perfetto/perfetto_metatrace.pbzero.h",
- "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
+ "protos/perfetto/trace/perfetto/tracing_service_event.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/perfetto/perfetto_metatrace.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/perfetto/tracing_service_event.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/power:cpp
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",
- ],
- 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/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",
- ],
+ 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",
+ ],
+ 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/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",
+ ],
}
// GN: //protos/perfetto/trace/power:cpp
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",
- ],
- 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/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",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ ],
+ 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/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",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/power:lite
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",
- ],
- 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/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",
- ],
+ 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",
+ ],
+ 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/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",
+ ],
}
// GN: //protos/perfetto/trace/power:lite
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",
- ],
- 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/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",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ ],
+ 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/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",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/power:zero
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",
- ],
- 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/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",
- ],
+ 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",
+ ],
+ 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/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",
+ ],
}
// GN: //protos/perfetto/trace/power:zero
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",
- ],
- 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/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",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ ],
+ 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/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",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace_processor:metrics_impl_zero
genrule {
- name: "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
- srcs: [
- "protos/perfetto/trace_processor/metrics_impl.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/trace_processor/metrics_impl.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
+ srcs: [
+ "protos/perfetto/trace_processor/metrics_impl.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/trace_processor/metrics_impl.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace_processor:metrics_impl_zero
genrule {
- name: "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace_processor/metrics_impl.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/protos/perfetto/trace_processor/metrics_impl.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace_processor/metrics_impl.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/trace_processor/metrics_impl.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace_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",
- ],
+ 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",
- ],
+ 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",
- "protos/perfetto/trace/profiling/smaps.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/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",
- "external/perfetto/protos/perfetto/trace/profiling/smaps.gen.cc",
- ],
+ 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",
+ "protos/perfetto/trace/profiling/smaps.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/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",
+ "external/perfetto/protos/perfetto/trace/profiling/smaps.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/profiling:cpp
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",
- "protos/perfetto/trace/profiling/smaps.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/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",
- "external/perfetto/protos/perfetto/trace/profiling/smaps.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "protos/perfetto/trace/profiling/smaps.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/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",
+ "external/perfetto/protos/perfetto/trace/profiling/smaps.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/profiling:lite
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",
- "protos/perfetto/trace/profiling/smaps.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/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",
- "external/perfetto/protos/perfetto/trace/profiling/smaps.pb.cc",
- ],
+ 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",
+ "protos/perfetto/trace/profiling/smaps.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/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",
+ "external/perfetto/protos/perfetto/trace/profiling/smaps.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/profiling:lite
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",
- "protos/perfetto/trace/profiling/smaps.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/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",
- "external/perfetto/protos/perfetto/trace/profiling/smaps.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "protos/perfetto/trace/profiling/smaps.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/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",
+ "external/perfetto/protos/perfetto/trace/profiling/smaps.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/profiling:zero
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",
- "protos/perfetto/trace/profiling/smaps.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/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",
- "external/perfetto/protos/perfetto/trace/profiling/smaps.pbzero.cc",
- ],
+ 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",
+ "protos/perfetto/trace/profiling/smaps.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/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",
+ "external/perfetto/protos/perfetto/trace/profiling/smaps.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/profiling:zero
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",
- "protos/perfetto/trace/profiling/smaps.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/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",
- "external/perfetto/protos/perfetto/trace/profiling/smaps.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "protos/perfetto/trace/profiling/smaps.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/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",
+ "external/perfetto/protos/perfetto/trace/profiling/smaps.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/ps:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_ps_cpp_gen",
- srcs: [
- "protos/perfetto/trace/ps/process_stats.proto",
- "protos/perfetto/trace/ps/process_tree.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/trace/ps/process_stats.gen.cc",
- "external/perfetto/protos/perfetto/trace/ps/process_tree.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_ps_cpp_gen",
+ srcs: [
+ "protos/perfetto/trace/ps/process_stats.proto",
+ "protos/perfetto/trace/ps/process_tree.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/trace/ps/process_stats.gen.cc",
+ "external/perfetto/protos/perfetto/trace/ps/process_tree.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/ps:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
- srcs: [
- "protos/perfetto/trace/ps/process_stats.proto",
- "protos/perfetto/trace/ps/process_tree.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/trace/ps/process_stats.gen.h",
- "external/perfetto/protos/perfetto/trace/ps/process_tree.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/ps/process_stats.proto",
+ "protos/perfetto/trace/ps/process_tree.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/trace/ps/process_stats.gen.h",
+ "external/perfetto/protos/perfetto/trace/ps/process_tree.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/ps:lite
genrule {
- name: "perfetto_protos_perfetto_trace_ps_lite_gen",
- srcs: [
- "protos/perfetto/trace/ps/process_stats.proto",
- "protos/perfetto/trace/ps/process_tree.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/ps/process_stats.pb.cc",
- "external/perfetto/protos/perfetto/trace/ps/process_tree.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_ps_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/ps/process_stats.proto",
+ "protos/perfetto/trace/ps/process_tree.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/ps/process_stats.pb.cc",
+ "external/perfetto/protos/perfetto/trace/ps/process_tree.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/ps:lite
genrule {
- name: "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
- srcs: [
- "protos/perfetto/trace/ps/process_stats.proto",
- "protos/perfetto/trace/ps/process_tree.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/ps/process_stats.pb.h",
- "external/perfetto/protos/perfetto/trace/ps/process_tree.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/ps/process_stats.proto",
+ "protos/perfetto/trace/ps/process_tree.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/ps/process_stats.pb.h",
+ "external/perfetto/protos/perfetto/trace/ps/process_tree.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/ps:zero
genrule {
- name: "perfetto_protos_perfetto_trace_ps_zero_gen",
- srcs: [
- "protos/perfetto/trace/ps/process_stats.proto",
- "protos/perfetto/trace/ps/process_tree.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/ps/process_stats.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/ps/process_tree.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_ps_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/ps/process_stats.proto",
+ "protos/perfetto/trace/ps/process_tree.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/ps/process_stats.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/ps/process_tree.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/ps:zero
genrule {
- name: "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace/ps/process_stats.proto",
- "protos/perfetto/trace/ps/process_tree.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/ps/process_stats.pbzero.h",
- "external/perfetto/protos/perfetto/trace/ps/process_tree.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/ps/process_stats.proto",
+ "protos/perfetto/trace/ps/process_tree.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/ps/process_stats.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/ps/process_tree.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/sys_stats:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
- srcs: [
- "protos/perfetto/trace/sys_stats/sys_stats.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/trace/sys_stats/sys_stats.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
+ srcs: [
+ "protos/perfetto/trace/sys_stats/sys_stats.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/trace/sys_stats/sys_stats.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/sys_stats:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_sys_stats_cpp_gen_headers",
- srcs: [
- "protos/perfetto/trace/sys_stats/sys_stats.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/trace/sys_stats/sys_stats.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_sys_stats_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/sys_stats/sys_stats.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/trace/sys_stats/sys_stats.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/sys_stats:lite
genrule {
- name: "perfetto_protos_perfetto_trace_sys_stats_lite_gen",
- srcs: [
- "protos/perfetto/trace/sys_stats/sys_stats.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/sys_stats/sys_stats.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_sys_stats_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/sys_stats/sys_stats.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/sys_stats/sys_stats.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/sys_stats:lite
genrule {
- name: "perfetto_protos_perfetto_trace_sys_stats_lite_gen_headers",
- srcs: [
- "protos/perfetto/trace/sys_stats/sys_stats.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/sys_stats/sys_stats.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_sys_stats_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/sys_stats/sys_stats.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/sys_stats/sys_stats.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/sys_stats:zero
genrule {
- name: "perfetto_protos_perfetto_trace_sys_stats_zero_gen",
- srcs: [
- "protos/perfetto/trace/sys_stats/sys_stats.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/sys_stats/sys_stats.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_sys_stats_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/sys_stats/sys_stats.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/sys_stats/sys_stats.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/sys_stats:zero
genrule {
- name: "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace/sys_stats/sys_stats.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/sys_stats/sys_stats.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/sys_stats/sys_stats.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/sys_stats/sys_stats.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/system_info:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_system_info_cpp_gen",
- srcs: [
- "protos/perfetto/trace/system_info/cpu_info.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/trace/system_info/cpu_info.gen.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_system_info_cpp_gen",
+ srcs: [
+ "protos/perfetto/trace/system_info/cpu_info.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/trace/system_info/cpu_info.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/system_info:cpp
genrule {
- name: "perfetto_protos_perfetto_trace_system_info_cpp_gen_headers",
- srcs: [
- "protos/perfetto/trace/system_info/cpu_info.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/trace/system_info/cpu_info.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_system_info_cpp_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/system_info/cpu_info.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/trace/system_info/cpu_info.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/system_info:lite
genrule {
- name: "perfetto_protos_perfetto_trace_system_info_lite_gen",
- srcs: [
- "protos/perfetto/trace/system_info/cpu_info.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/system_info/cpu_info.pb.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_system_info_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/system_info/cpu_info.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/system_info/cpu_info.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/system_info:lite
genrule {
- name: "perfetto_protos_perfetto_trace_system_info_lite_gen_headers",
- srcs: [
- "protos/perfetto/trace/system_info/cpu_info.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/system_info/cpu_info.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_system_info_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/system_info/cpu_info.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/system_info/cpu_info.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/system_info:zero
genrule {
- name: "perfetto_protos_perfetto_trace_system_info_zero_gen",
- srcs: [
- "protos/perfetto/trace/system_info/cpu_info.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/system_info/cpu_info.pbzero.cc",
- ],
+ name: "perfetto_protos_perfetto_trace_system_info_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/system_info/cpu_info.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/system_info/cpu_info.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/system_info:zero
genrule {
- name: "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
- srcs: [
- "protos/perfetto/trace/system_info/cpu_info.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/system_info/cpu_info.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/system_info/cpu_info.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/system_info/cpu_info.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/track_event:cpp
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",
- "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",
- "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/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",
- "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.cc",
- "external/perfetto/protos/perfetto/trace/track_event/source_location.gen.cc",
- "external/perfetto/protos/perfetto/trace/track_event/task_execution.gen.cc",
- "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.cc",
- "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.gen.cc",
- "external/perfetto/protos/perfetto/trace/track_event/track_event.gen.cc",
- ],
+ 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",
+ "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",
+ "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/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",
+ "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/source_location.gen.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/task_execution.gen.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.gen.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/track_event.gen.cc",
+ ],
}
// GN: //protos/perfetto/trace/track_event:cpp
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",
- "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",
- "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/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",
- "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.h",
- "external/perfetto/protos/perfetto/trace/track_event/source_location.gen.h",
- "external/perfetto/protos/perfetto/trace/track_event/task_execution.gen.h",
- "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.h",
- "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.gen.h",
- "external/perfetto/protos/perfetto/trace/track_event/track_event.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "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",
+ "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/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",
+ "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.h",
+ "external/perfetto/protos/perfetto/trace/track_event/source_location.gen.h",
+ "external/perfetto/protos/perfetto/trace/track_event/task_execution.gen.h",
+ "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.h",
+ "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.gen.h",
+ "external/perfetto/protos/perfetto/trace/track_event/track_event.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/track_event:lite
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",
- "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 --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",
- "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.cc",
- "external/perfetto/protos/perfetto/trace/track_event/source_location.pb.cc",
- "external/perfetto/protos/perfetto/trace/track_event/task_execution.pb.cc",
- "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pb.cc",
- "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pb.cc",
- "external/perfetto/protos/perfetto/trace/track_event/track_event.pb.cc",
- ],
+ 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",
+ "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 --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",
+ "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/source_location.pb.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/task_execution.pb.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pb.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pb.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/track_event.pb.cc",
+ ],
}
// GN: //protos/perfetto/trace/track_event:lite
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",
- "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 --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",
- "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.h",
- "external/perfetto/protos/perfetto/trace/track_event/source_location.pb.h",
- "external/perfetto/protos/perfetto/trace/track_event/task_execution.pb.h",
- "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pb.h",
- "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pb.h",
- "external/perfetto/protos/perfetto/trace/track_event/track_event.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "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 --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",
+ "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.h",
+ "external/perfetto/protos/perfetto/trace/track_event/source_location.pb.h",
+ "external/perfetto/protos/perfetto/trace/track_event/task_execution.pb.h",
+ "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pb.h",
+ "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pb.h",
+ "external/perfetto/protos/perfetto/trace/track_event/track_event.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/perfetto/trace/track_event: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",
- ],
+ 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",
- "protos/perfetto/trace/track_event/process_descriptor.proto",
- "protos/perfetto/trace/track_event/source_location.proto",
- "protos/perfetto/trace/track_event/task_execution.proto",
- "protos/perfetto/trace/track_event/thread_descriptor.proto",
- "protos/perfetto/trace/track_event/track_descriptor.proto",
- "protos/perfetto/trace/track_event/track_event.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- 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",
- "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.cc",
- ],
+ 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",
+ "protos/perfetto/trace/track_event/process_descriptor.proto",
+ "protos/perfetto/trace/track_event/source_location.proto",
+ "protos/perfetto/trace/track_event/task_execution.proto",
+ "protos/perfetto/trace/track_event/thread_descriptor.proto",
+ "protos/perfetto/trace/track_event/track_descriptor.proto",
+ "protos/perfetto/trace/track_event/track_event.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ 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",
+ "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.cc",
+ ],
}
// GN: //protos/perfetto/trace/track_event:zero
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",
- "protos/perfetto/trace/track_event/process_descriptor.proto",
- "protos/perfetto/trace/track_event/source_location.proto",
- "protos/perfetto/trace/track_event/task_execution.proto",
- "protos/perfetto/trace/track_event/thread_descriptor.proto",
- "protos/perfetto/trace/track_event/track_descriptor.proto",
- "protos/perfetto/trace/track_event/track_event.proto",
- ],
- tools: [
- "aprotoc",
- "protozero_plugin",
- ],
- 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",
- "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.h",
- "external/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h",
- "external/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.h",
- "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pbzero.h",
- "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pbzero.h",
- "external/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "protos/perfetto/trace/track_event/process_descriptor.proto",
+ "protos/perfetto/trace/track_event/source_location.proto",
+ "protos/perfetto/trace/track_event/task_execution.proto",
+ "protos/perfetto/trace/track_event/thread_descriptor.proto",
+ "protos/perfetto/trace/track_event/track_descriptor.proto",
+ "protos/perfetto/trace/track_event/track_event.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protozero_plugin",
+ ],
+ 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",
+ "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //protos/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",
- ],
+ 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",
- srcs: [
- "protos/third_party/pprof/profile.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/third_party/pprof/profile.pbzero.cc",
- ],
+ name: "perfetto_protos_third_party_pprof_zero_gen",
+ srcs: [
+ "protos/third_party/pprof/profile.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/third_party/pprof/profile.pbzero.cc",
+ ],
}
// GN: //protos/third_party/pprof:zero
genrule {
- name: "perfetto_protos_third_party_pprof_zero_gen_headers",
- srcs: [
- "protos/third_party/pprof/profile.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/third_party/pprof/profile.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_protos_third_party_pprof_zero_gen_headers",
+ srcs: [
+ "protos/third_party/pprof/profile.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/third_party/pprof/profile.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //src/android_internal:headers
filegroup {
- name: "perfetto_src_android_internal_headers",
+ name: "perfetto_src_android_internal_headers",
}
// GN: //src/android_internal:lazy_library_loader
filegroup {
- name: "perfetto_src_android_internal_lazy_library_loader",
- srcs: [
- "src/android_internal/lazy_library_loader.cc",
- ],
+ name: "perfetto_src_android_internal_lazy_library_loader",
+ srcs: [
+ "src/android_internal/lazy_library_loader.cc",
+ ],
}
// GN: //src/android_stats:android_stats
filegroup {
- name: "perfetto_src_android_stats_android_stats",
- srcs: [
- "src/android_stats/statsd_logging_helper.cc",
- ],
+ 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",
+ 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",
- ],
+ 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",
+ ],
}
// GN: //src/base:test_support
filegroup {
- name: "perfetto_src_base_test_support",
- srcs: [
- "src/base/test/test_task_runner.cc",
- "src/base/test/utils.cc",
- "src/base/test/vm_test_utils.cc",
- ],
+ name: "perfetto_src_base_test_support",
+ srcs: [
+ "src/base/test/test_task_runner.cc",
+ "src/base/test/tmp_dir_tree.cc",
+ "src/base/test/utils.cc",
+ "src/base/test/vm_test_utils.cc",
+ ],
}
// GN: //src/base:unittests
filegroup {
- name: "perfetto_src_base_unittests",
- srcs: [
- "src/base/circular_queue_unittest.cc",
- "src/base/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",
- "src/base/string_view_unittest.cc",
- "src/base/string_writer_unittest.cc",
- "src/base/subprocess_unittest.cc",
- "src/base/task_runner_unittest.cc",
- "src/base/temp_file_unittest.cc",
- "src/base/thread_checker_unittest.cc",
- "src/base/thread_task_runner_unittest.cc",
- "src/base/time_unittest.cc",
- "src/base/unix_socket_unittest.cc",
- "src/base/utils_unittest.cc",
- "src/base/uuid_unittest.cc",
- "src/base/watchdog_posix_unittest.cc",
- "src/base/watchdog_unittest.cc",
- "src/base/weak_ptr_unittest.cc",
- ],
+ name: "perfetto_src_base_unittests",
+ 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",
+ "src/base/string_view_unittest.cc",
+ "src/base/string_writer_unittest.cc",
+ "src/base/subprocess_unittest.cc",
+ "src/base/task_runner_unittest.cc",
+ "src/base/temp_file_unittest.cc",
+ "src/base/thread_checker_unittest.cc",
+ "src/base/thread_task_runner_unittest.cc",
+ "src/base/time_unittest.cc",
+ "src/base/unix_socket_unittest.cc",
+ "src/base/utils_unittest.cc",
+ "src/base/uuid_unittest.cc",
+ "src/base/watchdog_posix_unittest.cc",
+ "src/base/watchdog_unittest.cc",
+ "src/base/weak_ptr_unittest.cc",
+ ],
}
// GN: //src/base:unix_socket
filegroup {
- name: "perfetto_src_base_unix_socket",
- srcs: [
- "src/base/unix_socket.cc",
- ],
+ name: "perfetto_src_base_unix_socket",
+ srcs: [
+ "src/base/unix_socket.cc",
+ ],
}
// 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",
- ],
+ 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",
- srcs: [
- "src/ipc/client_impl.cc",
- "src/ipc/service_proxy.cc",
- ],
+ name: "perfetto_src_ipc_client",
+ srcs: [
+ "src/ipc/client_impl.cc",
+ "src/ipc/service_proxy.cc",
+ ],
}
// GN: //src/ipc:common
filegroup {
- name: "perfetto_src_ipc_common",
- srcs: [
- "src/ipc/buffered_frame_deserializer.cc",
- "src/ipc/deferred.cc",
- "src/ipc/virtual_destructors.cc",
- ],
+ name: "perfetto_src_ipc_common",
+ srcs: [
+ "src/ipc/buffered_frame_deserializer.cc",
+ "src/ipc/deferred.cc",
+ "src/ipc/virtual_destructors.cc",
+ ],
}
// GN: //src/ipc:host
filegroup {
- name: "perfetto_src_ipc_host",
- srcs: [
- "src/ipc/host_impl.cc",
- ],
+ name: "perfetto_src_ipc_host",
+ srcs: [
+ "src/ipc/host_impl.cc",
+ ],
}
// GN: //src/ipc:perfetto_ipc
filegroup {
- name: "perfetto_src_ipc_perfetto_ipc",
+ name: "perfetto_src_ipc_perfetto_ipc",
}
// GN: //src/ipc:test_messages_cpp
genrule {
- name: "perfetto_src_ipc_test_messages_cpp_gen",
- srcs: [
- "src/ipc/test/client_unittest_messages.proto",
- "src/ipc/test/deferred_unittest_messages.proto",
- "src/ipc/test/greeter_service.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/src/ipc/test/client_unittest_messages.gen.cc",
- "external/perfetto/src/ipc/test/deferred_unittest_messages.gen.cc",
- "external/perfetto/src/ipc/test/greeter_service.gen.cc",
- ],
+ name: "perfetto_src_ipc_test_messages_cpp_gen",
+ srcs: [
+ "src/ipc/test/client_unittest_messages.proto",
+ "src/ipc/test/deferred_unittest_messages.proto",
+ "src/ipc/test/greeter_service.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/src/ipc/test/client_unittest_messages.gen.cc",
+ "external/perfetto/src/ipc/test/deferred_unittest_messages.gen.cc",
+ "external/perfetto/src/ipc/test/greeter_service.gen.cc",
+ ],
}
// GN: //src/ipc:test_messages_cpp
genrule {
- name: "perfetto_src_ipc_test_messages_cpp_gen_headers",
- srcs: [
- "src/ipc/test/client_unittest_messages.proto",
- "src/ipc/test/deferred_unittest_messages.proto",
- "src/ipc/test/greeter_service.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/src/ipc/test/client_unittest_messages.gen.h",
- "external/perfetto/src/ipc/test/deferred_unittest_messages.gen.h",
- "external/perfetto/src/ipc/test/greeter_service.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_src_ipc_test_messages_cpp_gen_headers",
+ srcs: [
+ "src/ipc/test/client_unittest_messages.proto",
+ "src/ipc/test/deferred_unittest_messages.proto",
+ "src/ipc/test/greeter_service.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/src/ipc/test/client_unittest_messages.gen.h",
+ "external/perfetto/src/ipc/test/deferred_unittest_messages.gen.h",
+ "external/perfetto/src/ipc/test/greeter_service.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //src/ipc:test_messages_ipc
genrule {
- name: "perfetto_src_ipc_test_messages_ipc_gen",
- srcs: [
- "src/ipc/test/client_unittest_messages.proto",
- "src/ipc/test/deferred_unittest_messages.proto",
- "src/ipc/test/greeter_service.proto",
- ],
- tools: [
- "aprotoc",
- "ipc_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/src/ipc/test/client_unittest_messages.ipc.cc",
- "external/perfetto/src/ipc/test/deferred_unittest_messages.ipc.cc",
- "external/perfetto/src/ipc/test/greeter_service.ipc.cc",
- ],
+ name: "perfetto_src_ipc_test_messages_ipc_gen",
+ srcs: [
+ "src/ipc/test/client_unittest_messages.proto",
+ "src/ipc/test/deferred_unittest_messages.proto",
+ "src/ipc/test/greeter_service.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "ipc_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/src/ipc/test/client_unittest_messages.ipc.cc",
+ "external/perfetto/src/ipc/test/deferred_unittest_messages.ipc.cc",
+ "external/perfetto/src/ipc/test/greeter_service.ipc.cc",
+ ],
}
// GN: //src/ipc:test_messages_ipc
genrule {
- name: "perfetto_src_ipc_test_messages_ipc_gen_headers",
- srcs: [
- "src/ipc/test/client_unittest_messages.proto",
- "src/ipc/test/deferred_unittest_messages.proto",
- "src/ipc/test/greeter_service.proto",
- ],
- tools: [
- "aprotoc",
- "ipc_plugin",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
- out: [
- "external/perfetto/src/ipc/test/client_unittest_messages.ipc.h",
- "external/perfetto/src/ipc/test/deferred_unittest_messages.ipc.h",
- "external/perfetto/src/ipc/test/greeter_service.ipc.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_src_ipc_test_messages_ipc_gen_headers",
+ srcs: [
+ "src/ipc/test/client_unittest_messages.proto",
+ "src/ipc/test/deferred_unittest_messages.proto",
+ "src/ipc/test/greeter_service.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "ipc_plugin",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+ out: [
+ "external/perfetto/src/ipc/test/client_unittest_messages.ipc.h",
+ "external/perfetto/src/ipc/test/deferred_unittest_messages.ipc.h",
+ "external/perfetto/src/ipc/test/greeter_service.ipc.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //src/ipc:unittests
filegroup {
- name: "perfetto_src_ipc_unittests",
- srcs: [
- "src/ipc/buffered_frame_deserializer_unittest.cc",
- "src/ipc/client_impl_unittest.cc",
- "src/ipc/deferred_unittest.cc",
- "src/ipc/host_impl_unittest.cc",
- "src/ipc/test/ipc_integrationtest.cc",
- ],
+ name: "perfetto_src_ipc_unittests",
+ srcs: [
+ "src/ipc/buffered_frame_deserializer_unittest.cc",
+ "src/ipc/client_impl_unittest.cc",
+ "src/ipc/deferred_unittest.cc",
+ "src/ipc/host_impl_unittest.cc",
+ "src/ipc/test/ipc_integrationtest.cc",
+ ],
}
// GN: //src/kallsyms:kallsyms
filegroup {
- name: "perfetto_src_kallsyms_kallsyms",
- srcs: [
- "src/kallsyms/kernel_symbol_map.cc",
- "src/kallsyms/lazy_kernel_symbolizer.cc",
- ],
+ 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",
- ],
+ 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_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",
+ ],
}
// GN: //src/perfetto_cmd:perfetto_cmd
filegroup {
- name: "perfetto_src_perfetto_cmd_perfetto_cmd",
- srcs: [
- "src/perfetto_cmd/config.cc",
- "src/perfetto_cmd/packet_writer.cc",
- "src/perfetto_cmd/pbtxt_to_pb.cc",
- "src/perfetto_cmd/perfetto_cmd.cc",
- "src/perfetto_cmd/perfetto_cmd_android.cc",
- "src/perfetto_cmd/rate_limiter.cc",
- ],
+ name: "perfetto_src_perfetto_cmd_perfetto_cmd",
+ srcs: [
+ "src/perfetto_cmd/config.cc",
+ "src/perfetto_cmd/packet_writer.cc",
+ "src/perfetto_cmd/pbtxt_to_pb.cc",
+ "src/perfetto_cmd/perfetto_cmd.cc",
+ "src/perfetto_cmd/perfetto_cmd_android.cc",
+ "src/perfetto_cmd/rate_limiter.cc",
+ ],
}
// GN: //src/perfetto_cmd:protos
genrule {
- name: "perfetto_src_perfetto_cmd_protos_gen",
- srcs: [
- "src/perfetto_cmd/perfetto_cmd_state.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/src/perfetto_cmd/perfetto_cmd_state.gen.cc",
- ],
+ name: "perfetto_src_perfetto_cmd_protos_gen",
+ srcs: [
+ "src/perfetto_cmd/perfetto_cmd_state.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/src/perfetto_cmd/perfetto_cmd_state.gen.cc",
+ ],
}
// GN: //src/perfetto_cmd:protos
genrule {
- name: "perfetto_src_perfetto_cmd_protos_gen_headers",
- srcs: [
- "src/perfetto_cmd/perfetto_cmd_state.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/src/perfetto_cmd/perfetto_cmd_state.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_src_perfetto_cmd_protos_gen_headers",
+ srcs: [
+ "src/perfetto_cmd/perfetto_cmd_state.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/src/perfetto_cmd/perfetto_cmd_state.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //src/perfetto_cmd:trigger_perfetto_cmd
filegroup {
- name: "perfetto_src_perfetto_cmd_trigger_perfetto_cmd",
- srcs: [
- "src/perfetto_cmd/trigger_perfetto.cc",
- ],
+ name: "perfetto_src_perfetto_cmd_trigger_perfetto_cmd",
+ srcs: [
+ "src/perfetto_cmd/trigger_perfetto.cc",
+ ],
}
// GN: //src/perfetto_cmd:trigger_producer
filegroup {
- name: "perfetto_src_perfetto_cmd_trigger_producer",
- srcs: [
- "src/perfetto_cmd/trigger_producer.cc",
- ],
+ name: "perfetto_src_perfetto_cmd_trigger_producer",
+ srcs: [
+ "src/perfetto_cmd/trigger_producer.cc",
+ ],
}
// GN: //src/perfetto_cmd:unittests
filegroup {
- name: "perfetto_src_perfetto_cmd_unittests",
- srcs: [
- "src/perfetto_cmd/config_unittest.cc",
- "src/perfetto_cmd/packet_writer_unittest.cc",
- "src/perfetto_cmd/pbtxt_to_pb_unittest.cc",
- "src/perfetto_cmd/rate_limiter_unittest.cc",
- ],
+ name: "perfetto_src_perfetto_cmd_unittests",
+ srcs: [
+ "src/perfetto_cmd/config_unittest.cc",
+ "src/perfetto_cmd/packet_writer_unittest.cc",
+ "src/perfetto_cmd/pbtxt_to_pb_unittest.cc",
+ "src/perfetto_cmd/rate_limiter_unittest.cc",
+ ],
}
// GN: //src/profiling/common:callstack_trie
filegroup {
- name: "perfetto_src_profiling_common_callstack_trie",
- srcs: [
- "src/profiling/common/callstack_trie.cc",
- ],
+ name: "perfetto_src_profiling_common_callstack_trie",
+ srcs: [
+ "src/profiling/common/callstack_trie.cc",
+ ],
}
// GN: //src/profiling/common:interner
filegroup {
- name: "perfetto_src_profiling_common_interner",
+ name: "perfetto_src_profiling_common_interner",
}
// GN: //src/profiling/common:interning_output
filegroup {
- name: "perfetto_src_profiling_common_interning_output",
- srcs: [
- "src/profiling/common/interning_output.cc",
- ],
+ name: "perfetto_src_profiling_common_interning_output",
+ srcs: [
+ "src/profiling/common/interning_output.cc",
+ ],
}
// GN: //src/profiling/common:proc_utils
filegroup {
- name: "perfetto_src_profiling_common_proc_utils",
- srcs: [
- "src/profiling/common/proc_utils.cc",
- ],
+ name: "perfetto_src_profiling_common_proc_utils",
+ srcs: [
+ "src/profiling/common/proc_utils.cc",
+ ],
}
// GN: //src/profiling/common:producer_support
filegroup {
- name: "perfetto_src_profiling_common_producer_support",
- srcs: [
- "src/profiling/common/producer_support.cc",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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",
+ ],
}
// GN: //src/profiling/common:unwind_support
filegroup {
- name: "perfetto_src_profiling_common_unwind_support",
- srcs: [
- "src/profiling/common/unwind_support.cc",
- ],
+ name: "perfetto_src_profiling_common_unwind_support",
+ srcs: [
+ "src/profiling/common/unwind_support.cc",
+ ],
}
// GN: //src/profiling:deobfuscator
filegroup {
- name: "perfetto_src_profiling_deobfuscator",
- srcs: [
- "src/profiling/deobfuscator.cc",
- ],
+ name: "perfetto_src_profiling_deobfuscator",
+ srcs: [
+ "src/profiling/deobfuscator.cc",
+ ],
}
// GN: //src/profiling/memory:bionic_libc_platform_headers_on_android
filegroup {
- name: "perfetto_src_profiling_memory_bionic_libc_platform_headers_on_android",
+ 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",
- ],
+ 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",
- ],
+ 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",
- ],
+ name: "perfetto_src_profiling_memory_client_api_standalone",
+ srcs: [
+ "src/profiling/memory/client_api_factory_standalone.cc",
+ ],
}
// GN: //src/profiling/memory:daemon
filegroup {
- name: "perfetto_src_profiling_memory_daemon",
- srcs: [
- "src/profiling/memory/bookkeeping.cc",
- "src/profiling/memory/bookkeeping_dump.cc",
- "src/profiling/memory/heapprofd_producer.cc",
- "src/profiling/memory/java_hprof_producer.cc",
- "src/profiling/memory/log_histogram.cc",
- "src/profiling/memory/system_property.cc",
- "src/profiling/memory/unwinding.cc",
- ],
+ name: "perfetto_src_profiling_memory_daemon",
+ srcs: [
+ "src/profiling/memory/bookkeeping.cc",
+ "src/profiling/memory/bookkeeping_dump.cc",
+ "src/profiling/memory/heapprofd_producer.cc",
+ "src/profiling/memory/java_hprof_producer.cc",
+ "src/profiling/memory/log_histogram.cc",
+ "src/profiling/memory/system_property.cc",
+ "src/profiling/memory/unwinding.cc",
+ ],
}
// GN: //src/profiling/memory:end_to_end_tests
filegroup {
- name: "perfetto_src_profiling_memory_end_to_end_tests",
- srcs: [
- "src/profiling/memory/heapprofd_end_to_end_test.cc",
- ],
+ name: "perfetto_src_profiling_memory_end_to_end_tests",
+ srcs: [
+ "src/profiling/memory/heapprofd_end_to_end_test.cc",
+ ],
}
// GN: //src/profiling/memory:heapprofd_main
filegroup {
- name: "perfetto_src_profiling_memory_heapprofd_main",
- srcs: [
- "src/profiling/memory/heapprofd.cc",
- ],
+ name: "perfetto_src_profiling_memory_heapprofd_main",
+ srcs: [
+ "src/profiling/memory/heapprofd.cc",
+ ],
}
// GN: //src/profiling/memory:malloc_interceptor_bionic_hooks
filegroup {
- name: "perfetto_src_profiling_memory_malloc_interceptor_bionic_hooks",
- srcs: [
- "src/profiling/memory/malloc_interceptor_bionic_hooks.cc",
- ],
+ name: "perfetto_src_profiling_memory_malloc_interceptor_bionic_hooks",
+ srcs: [
+ "src/profiling/memory/malloc_interceptor_bionic_hooks.cc",
+ ],
}
// GN: //src/profiling/memory:ring_buffer
filegroup {
- name: "perfetto_src_profiling_memory_ring_buffer",
- srcs: [
- "src/profiling/memory/shared_ring_buffer.cc",
- ],
+ name: "perfetto_src_profiling_memory_ring_buffer",
+ srcs: [
+ "src/profiling/memory/shared_ring_buffer.cc",
+ ],
}
// GN: //src/profiling/memory:ring_buffer_unittests
filegroup {
- name: "perfetto_src_profiling_memory_ring_buffer_unittests",
- srcs: [
- "src/profiling/memory/shared_ring_buffer_unittest.cc",
- ],
+ name: "perfetto_src_profiling_memory_ring_buffer_unittests",
+ srcs: [
+ "src/profiling/memory/shared_ring_buffer_unittest.cc",
+ ],
}
// GN: //src/profiling/memory:scoped_spinlock
filegroup {
- name: "perfetto_src_profiling_memory_scoped_spinlock",
- srcs: [
- "src/profiling/memory/scoped_spinlock.cc",
- ],
+ name: "perfetto_src_profiling_memory_scoped_spinlock",
+ srcs: [
+ "src/profiling/memory/scoped_spinlock.cc",
+ ],
}
// GN: //src/profiling/memory:unittests
filegroup {
- name: "perfetto_src_profiling_memory_unittests",
- srcs: [
- "src/profiling/memory/bookkeeping_unittest.cc",
- "src/profiling/memory/client_unittest.cc",
- "src/profiling/memory/heapprofd_producer_unittest.cc",
- "src/profiling/memory/parse_smaps_unittest.cc",
- "src/profiling/memory/sampler_unittest.cc",
- "src/profiling/memory/system_property_unittest.cc",
- "src/profiling/memory/unwinding_unittest.cc",
- "src/profiling/memory/wire_protocol_unittest.cc",
- ],
+ name: "perfetto_src_profiling_memory_unittests",
+ srcs: [
+ "src/profiling/memory/bookkeeping_unittest.cc",
+ "src/profiling/memory/client_unittest.cc",
+ "src/profiling/memory/heapprofd_producer_unittest.cc",
+ "src/profiling/memory/parse_smaps_unittest.cc",
+ "src/profiling/memory/sampler_unittest.cc",
+ "src/profiling/memory/system_property_unittest.cc",
+ "src/profiling/memory/unwinding_unittest.cc",
+ "src/profiling/memory/wire_protocol_unittest.cc",
+ ],
}
// GN: //src/profiling/memory:wire_protocol
filegroup {
- name: "perfetto_src_profiling_memory_wire_protocol",
- srcs: [
- "src/profiling/memory/wire_protocol.cc",
- ],
+ name: "perfetto_src_profiling_memory_wire_protocol",
+ srcs: [
+ "src/profiling/memory/wire_protocol.cc",
+ ],
}
// GN: //src/profiling/memory:wrap_allocators
filegroup {
- name: "perfetto_src_profiling_memory_wrap_allocators",
- srcs: [
- "src/profiling/memory/wrap_allocators.cc",
- ],
+ 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",
+ name: "perfetto_src_profiling_perf_common_types",
}
// GN: //src/profiling/perf:proc_descriptors
filegroup {
- name: "perfetto_src_profiling_perf_proc_descriptors",
- srcs: [
- "src/profiling/perf/proc_descriptors.cc",
- ],
+ name: "perfetto_src_profiling_perf_proc_descriptors",
+ srcs: [
+ "src/profiling/perf/proc_descriptors.cc",
+ ],
}
// GN: //src/profiling/perf:producer
filegroup {
- name: "perfetto_src_profiling_perf_producer",
- srcs: [
- "src/profiling/perf/event_config.cc",
- "src/profiling/perf/event_reader.cc",
- "src/profiling/perf/perf_producer.cc",
- ],
+ name: "perfetto_src_profiling_perf_producer",
+ srcs: [
+ "src/profiling/perf/event_config.cc",
+ "src/profiling/perf/event_reader.cc",
+ "src/profiling/perf/perf_producer.cc",
+ ],
}
// GN: //src/profiling/perf:producer_unittests
filegroup {
- name: "perfetto_src_profiling_perf_producer_unittests",
- srcs: [
- "src/profiling/perf/event_config_unittest.cc",
- "src/profiling/perf/unwind_queue_unittest.cc",
- ],
+ name: "perfetto_src_profiling_perf_producer_unittests",
+ srcs: [
+ "src/profiling/perf/event_config_unittest.cc",
+ "src/profiling/perf/unwind_queue_unittest.cc",
+ ],
}
// GN: //src/profiling/perf:regs_parsing
filegroup {
- name: "perfetto_src_profiling_perf_regs_parsing",
- srcs: [
- "src/profiling/perf/regs_parsing.cc",
- ],
+ name: "perfetto_src_profiling_perf_regs_parsing",
+ srcs: [
+ "src/profiling/perf/regs_parsing.cc",
+ ],
}
// GN: //src/profiling/perf:traced_perf_main
filegroup {
- name: "perfetto_src_profiling_perf_traced_perf_main",
- srcs: [
- "src/profiling/perf/traced_perf.cc",
- ],
+ name: "perfetto_src_profiling_perf_traced_perf_main",
+ srcs: [
+ "src/profiling/perf/traced_perf.cc",
+ ],
}
// GN: //src/profiling/perf:unwinding
filegroup {
- name: "perfetto_src_profiling_perf_unwinding",
- srcs: [
- "src/profiling/perf/unwinding.cc",
- ],
+ name: "perfetto_src_profiling_perf_unwinding",
+ srcs: [
+ "src/profiling/perf/unwinding.cc",
+ ],
}
// GN: //src/profiling/symbolizer:symbolize_database
filegroup {
- name: "perfetto_src_profiling_symbolizer_symbolize_database",
- srcs: [
- "src/profiling/symbolizer/symbolize_database.cc",
- ],
+ name: "perfetto_src_profiling_symbolizer_symbolize_database",
+ srcs: [
+ "src/profiling/symbolizer/symbolize_database.cc",
+ ],
}
// GN: //src/profiling/symbolizer:symbolizer
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",
- ],
+ name: "perfetto_src_profiling_symbolizer_symbolizer",
+ srcs: [
+ "src/profiling/symbolizer/breakpad_parser.cc",
+ "src/profiling/symbolizer/breakpad_symbolizer.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",
- ],
+ name: "perfetto_src_profiling_symbolizer_unittests",
+ srcs: [
+ "src/profiling/symbolizer/breakpad_parser_unittest.cc",
+ "src/profiling/symbolizer/breakpad_symbolizer_unittest.cc",
+ "src/profiling/symbolizer/local_symbolizer_unittest.cc",
+ ],
}
// GN: //src/profiling:unittests
filegroup {
- name: "perfetto_src_profiling_unittests",
- srcs: [
- "src/profiling/deobfuscator_unittest.cc",
- ],
+ name: "perfetto_src_profiling_unittests",
+ srcs: [
+ "src/profiling/deobfuscator_unittest.cc",
+ ],
}
// GN: //src/protozero/filtering:bytecode_common
filegroup {
- name: "perfetto_src_protozero_filtering_bytecode_common",
+ 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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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:proto_ring_buffer
filegroup {
- name: "perfetto_src_protozero_proto_ring_buffer",
- srcs: [
- "src/protozero/proto_ring_buffer.cc",
- ],
+ name: "perfetto_src_protozero_proto_ring_buffer",
+ srcs: [
+ "src/protozero/proto_ring_buffer.cc",
+ ],
}
// GN: //src/protozero/protoc_plugin:cppgen_plugin
cc_binary_host {
- name: "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_src_base_base",
- "src/protozero/protoc_plugin/cppgen_plugin.cc",
- ],
- static_libs: [
- "libprotoc",
- ],
- generated_headers: [
- "perfetto_src_base_version_gen_h",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- ],
+ name: "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_src_base_base",
+ "src/protozero/protoc_plugin/cppgen_plugin.cc",
+ ],
+ static_libs: [
+ "libprotoc",
+ ],
+ generated_headers: [
+ "perfetto_src_base_version_gen_h",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ ],
}
// GN: //src/protozero:protozero
filegroup {
- name: "perfetto_src_protozero_protozero",
- 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",
- ],
+ name: "perfetto_src_protozero_protozero",
+ 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",
+ ],
}
// 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",
- ],
+ 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",
- "src/protozero/test/example_proto/upper_import.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/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",
- "external/perfetto/src/protozero/test/example_proto/upper_import.gen.cc",
- ],
+ 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",
+ "src/protozero/test/example_proto/upper_import.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/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",
+ "external/perfetto/src/protozero/test/example_proto/upper_import.gen.cc",
+ ],
}
// GN: //src/protozero:testing_messages_cpp
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",
- "src/protozero/test/example_proto/upper_import.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/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",
- "external/perfetto/src/protozero/test/example_proto/upper_import.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "src/protozero/test/example_proto/upper_import.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/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",
+ "external/perfetto/src/protozero/test/example_proto/upper_import.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //src/protozero:testing_messages_lite
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",
- "src/protozero/test/example_proto/upper_import.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/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",
- "external/perfetto/src/protozero/test/example_proto/upper_import.pb.cc",
- ],
+ 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",
+ "src/protozero/test/example_proto/upper_import.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/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",
+ "external/perfetto/src/protozero/test/example_proto/upper_import.pb.cc",
+ ],
}
// GN: //src/protozero:testing_messages_lite
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",
- "src/protozero/test/example_proto/upper_import.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/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",
- "external/perfetto/src/protozero/test/example_proto/upper_import.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "src/protozero/test/example_proto/upper_import.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/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",
+ "external/perfetto/src/protozero/test/example_proto/upper_import.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //src/protozero:testing_messages_zero
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",
- "src/protozero/test/example_proto/upper_import.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/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",
- "external/perfetto/src/protozero/test/example_proto/upper_import.pbzero.cc",
- ],
+ 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",
+ "src/protozero/test/example_proto/upper_import.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/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",
+ "external/perfetto/src/protozero/test/example_proto/upper_import.pbzero.cc",
+ ],
}
// GN: //src/protozero:testing_messages_zero
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",
- "src/protozero/test/example_proto/upper_import.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/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",
- "external/perfetto/src/protozero/test/example_proto/upper_import.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ 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",
+ "src/protozero/test/example_proto/upper_import.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/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",
+ "external/perfetto/src/protozero/test/example_proto/upper_import.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //src/protozero:unittests
filegroup {
- name: "perfetto_src_protozero_unittests",
- srcs: [
- "src/protozero/copyable_ptr_unittest.cc",
- "src/protozero/message_handle_unittest.cc",
- "src/protozero/message_unittest.cc",
- "src/protozero/proto_decoder_unittest.cc",
- "src/protozero/proto_ring_buffer_unittest.cc",
- "src/protozero/proto_utils_unittest.cc",
- "src/protozero/scattered_stream_writer_unittest.cc",
- "src/protozero/test/cppgen_conformance_unittest.cc",
- "src/protozero/test/fake_scattered_buffer.cc",
- "src/protozero/test/protozero_conformance_unittest.cc",
- ],
+ name: "perfetto_src_protozero_unittests",
+ srcs: [
+ "src/protozero/copyable_ptr_unittest.cc",
+ "src/protozero/message_handle_unittest.cc",
+ "src/protozero/message_unittest.cc",
+ "src/protozero/proto_decoder_unittest.cc",
+ "src/protozero/proto_ring_buffer_unittest.cc",
+ "src/protozero/proto_utils_unittest.cc",
+ "src/protozero/scattered_stream_writer_unittest.cc",
+ "src/protozero/test/cppgen_conformance_unittest.cc",
+ "src/protozero/test/fake_scattered_buffer.cc",
+ "src/protozero/test/protozero_conformance_unittest.cc",
+ ],
}
// GN: //src/trace_processor/analysis:analysis
filegroup {
- name: "perfetto_src_trace_processor_analysis_analysis",
- srcs: [
- "src/trace_processor/analysis/describe_slice.cc",
- ],
+ name: "perfetto_src_trace_processor_analysis_analysis",
+ srcs: [
+ "src/trace_processor/analysis/describe_slice.cc",
+ ],
}
// GN: //src/trace_processor/containers:containers
filegroup {
- name: "perfetto_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",
- ],
+ name: "perfetto_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",
+ ],
}
// GN: //src/trace_processor/containers:unittests
filegroup {
- name: "perfetto_src_trace_processor_containers_unittests",
- srcs: [
- "src/trace_processor/containers/bit_vector_unittest.cc",
- "src/trace_processor/containers/null_term_string_view_unittest.cc",
- "src/trace_processor/containers/nullable_vector_unittest.cc",
- "src/trace_processor/containers/row_map_unittest.cc",
- "src/trace_processor/containers/string_pool_unittest.cc",
- ],
+ name: "perfetto_src_trace_processor_containers_unittests",
+ srcs: [
+ "src/trace_processor/containers/bit_vector_unittest.cc",
+ "src/trace_processor/containers/null_term_string_view_unittest.cc",
+ "src/trace_processor/containers/nullable_vector_unittest.cc",
+ "src/trace_processor/containers/row_map_unittest.cc",
+ "src/trace_processor/containers/string_pool_unittest.cc",
+ ],
}
// GN: //src/trace_processor/db:db
filegroup {
- name: "perfetto_src_trace_processor_db_db",
- srcs: [
- "src/trace_processor/db/column.cc",
- "src/trace_processor/db/table.cc",
- ],
+ name: "perfetto_src_trace_processor_db_db",
+ srcs: [
+ "src/trace_processor/db/column.cc",
+ "src/trace_processor/db/table.cc",
+ ],
}
// GN: //src/trace_processor/db:unittests
filegroup {
- name: "perfetto_src_trace_processor_db_unittests",
- srcs: [
- "src/trace_processor/db/compare_unittest.cc",
- "src/trace_processor/db/table_unittest.cc",
- ],
+ name: "perfetto_src_trace_processor_db_unittests",
+ srcs: [
+ "src/trace_processor/db/compare_unittest.cc",
+ "src/trace_processor/db/table_unittest.cc",
+ ],
}
// GN: //src/trace_processor:export_json
filegroup {
- name: "perfetto_src_trace_processor_export_json",
- srcs: [
- "src/trace_processor/export_json.cc",
- ],
+ name: "perfetto_src_trace_processor_export_json",
+ srcs: [
+ "src/trace_processor/export_json.cc",
+ ],
}
// GN: //src/trace_processor:ftrace_descriptors
filegroup {
- name: "perfetto_src_trace_processor_ftrace_descriptors",
- srcs: [
- "src/trace_processor/importers/ftrace/ftrace_descriptors.cc",
- ],
+ name: "perfetto_src_trace_processor_ftrace_descriptors",
+ srcs: [
+ "src/trace_processor/importers/ftrace/ftrace_descriptors.cc",
+ ],
}
// 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",
- ],
+ 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
filegroup {
- name: "perfetto_src_trace_processor_importers_common_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",
- "src/trace_processor/importers/common/system_info_tracker.cc",
- "src/trace_processor/importers/common/track_tracker.cc",
- ],
+ name: "perfetto_src_trace_processor_importers_common_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",
+ "src/trace_processor/importers/common/system_info_tracker.cc",
+ "src/trace_processor/importers/common/track_tracker.cc",
+ ],
}
// GN: //src/trace_processor/importers/common:unittests
filegroup {
- name: "perfetto_src_trace_processor_importers_common_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",
- ],
+ name: "perfetto_src_trace_processor_importers_common_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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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_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_flat_slice_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",
+ ],
}
// GN: //src/trace_processor:metatrace
filegroup {
- name: "perfetto_src_trace_processor_metatrace",
- srcs: [
- "src/trace_processor/tp_metatrace.cc",
- ],
+ name: "perfetto_src_trace_processor_metatrace",
+ srcs: [
+ "src/trace_processor/tp_metatrace.cc",
+ ],
}
// 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",
- ],
+ 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",
- ],
+ 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",
- ],
+ 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_multiuser.sql",
+ "src/trace_processor/metrics/android/android_multiuser_populator.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_sysui_cuj_jank_query.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/android_trace_quality.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/gpu_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/profiler_smaps.sql",
+ "src/trace_processor/metrics/android/span_view_stats.sql",
+ "src/trace_processor/metrics/android/thread_counter_span_view.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/gesture_flow_event.sql",
+ "src/trace_processor/metrics/chrome/gesture_flow_event_queuing_delay.sql",
+ "src/trace_processor/metrics/chrome/gesture_jank.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/chrome/touch_flow_event.sql",
+ "src/trace_processor/metrics/chrome/touch_flow_event_queuing_delay.sql",
+ "src/trace_processor/metrics/chrome/touch_jank.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",
- srcs: [
- "src/trace_processor/metrics/metrics.cc",
- ],
+ name: "perfetto_src_trace_processor_metrics_lib",
+ srcs: [
+ "src/trace_processor/metrics/metrics.cc",
+ ],
}
// GN: //src/trace_processor/metrics:unittests
filegroup {
- name: "perfetto_src_trace_processor_metrics_unittests",
- srcs: [
- "src/trace_processor/metrics/metrics_unittest.cc",
- ],
+ name: "perfetto_src_trace_processor_metrics_unittests",
+ srcs: [
+ "src/trace_processor/metrics/metrics_unittest.cc",
+ ],
+}
+
+// GN: //src/trace_processor/rpc:httpd
+filegroup {
+ name: "perfetto_src_trace_processor_rpc_httpd",
+ srcs: [
+ "src/trace_processor/rpc/httpd.cc",
+ ],
}
// GN: //src/trace_processor/rpc:rpc
filegroup {
- name: "perfetto_src_trace_processor_rpc_rpc",
- srcs: [
- "src/trace_processor/rpc/query_result_serializer.cc",
- "src/trace_processor/rpc/rpc.cc",
- ],
+ name: "perfetto_src_trace_processor_rpc_rpc",
+ srcs: [
+ "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/query_result_serializer_unittest.cc",
- ],
+ name: "perfetto_src_trace_processor_rpc_unittests",
+ srcs: [
+ "src/trace_processor/rpc/query_result_serializer_unittest.cc",
+ ],
}
// GN: //src/trace_processor/sqlite:sqlite
filegroup {
- name: "perfetto_src_trace_processor_sqlite_sqlite",
- srcs: [
- "src/trace_processor/sqlite/db_sqlite_table.cc",
- "src/trace_processor/sqlite/query_constraints.cc",
- "src/trace_processor/sqlite/span_join_operator_table.cc",
- "src/trace_processor/sqlite/sql_stats_table.cc",
- "src/trace_processor/sqlite/sqlite3_str_split.cc",
- "src/trace_processor/sqlite/sqlite_raw_table.cc",
- "src/trace_processor/sqlite/sqlite_table.cc",
- "src/trace_processor/sqlite/stats_table.cc",
- "src/trace_processor/sqlite/window_operator_table.cc",
- ],
+ name: "perfetto_src_trace_processor_sqlite_sqlite",
+ srcs: [
+ "src/trace_processor/sqlite/db_sqlite_table.cc",
+ "src/trace_processor/sqlite/query_constraints.cc",
+ "src/trace_processor/sqlite/span_join_operator_table.cc",
+ "src/trace_processor/sqlite/sql_stats_table.cc",
+ "src/trace_processor/sqlite/sqlite3_str_split.cc",
+ "src/trace_processor/sqlite/sqlite_raw_table.cc",
+ "src/trace_processor/sqlite/sqlite_table.cc",
+ "src/trace_processor/sqlite/stats_table.cc",
+ "src/trace_processor/sqlite/window_operator_table.cc",
+ ],
}
// GN: //src/trace_processor/sqlite:unittests
filegroup {
- name: "perfetto_src_trace_processor_sqlite_unittests",
- srcs: [
- "src/trace_processor/sqlite/db_sqlite_table_unittest.cc",
- "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",
- ],
+ name: "perfetto_src_trace_processor_sqlite_unittests",
+ srcs: [
+ "src/trace_processor/sqlite/db_sqlite_table_unittest.cc",
+ "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",
+ ],
}
// GN: //src/trace_processor:storage_full
filegroup {
- name: "perfetto_src_trace_processor_storage_full",
- srcs: [
- "src/trace_processor/importers/additional_modules.cc",
- "src/trace_processor/importers/ftrace/binder_tracker.cc",
- "src/trace_processor/importers/ftrace/ftrace_module_impl.cc",
- "src/trace_processor/importers/ftrace/ftrace_parser.cc",
- "src/trace_processor/importers/ftrace/ftrace_tokenizer.cc",
- "src/trace_processor/importers/ftrace/rss_stat_tracker.cc",
- "src/trace_processor/importers/ftrace/sched_event_tracker.cc",
- "src/trace_processor/importers/fuchsia/fuchsia_record.cc",
- "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc",
- "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc",
- "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc",
- "src/trace_processor/importers/gzip/gzip_trace_parser.cc",
- "src/trace_processor/importers/json/json_trace_parser.cc",
- "src/trace_processor/importers/json/json_trace_tokenizer.cc",
- "src/trace_processor/importers/json/json_tracker.cc",
- "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",
- "src/trace_processor/importers/proto/heap_graph_module.cc",
- "src/trace_processor/importers/proto/heap_graph_tracker.cc",
- "src/trace_processor/importers/proto/system_probes_module.cc",
- "src/trace_processor/importers/proto/system_probes_parser.cc",
- "src/trace_processor/importers/proto/vulkan_memory_tracker.cc",
- "src/trace_processor/importers/syscalls/syscall_tracker.cc",
- "src/trace_processor/importers/systrace/systrace_line_parser.cc",
- "src/trace_processor/importers/systrace/systrace_line_tokenizer.cc",
- "src/trace_processor/importers/systrace/systrace_parser.cc",
- "src/trace_processor/importers/systrace/systrace_trace_parser.cc",
- ],
+ name: "perfetto_src_trace_processor_storage_full",
+ srcs: [
+ "src/trace_processor/importers/additional_modules.cc",
+ "src/trace_processor/importers/ftrace/binder_tracker.cc",
+ "src/trace_processor/importers/ftrace/ftrace_module_impl.cc",
+ "src/trace_processor/importers/ftrace/ftrace_parser.cc",
+ "src/trace_processor/importers/ftrace/ftrace_tokenizer.cc",
+ "src/trace_processor/importers/ftrace/rss_stat_tracker.cc",
+ "src/trace_processor/importers/ftrace/sched_event_tracker.cc",
+ "src/trace_processor/importers/fuchsia/fuchsia_record.cc",
+ "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc",
+ "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc",
+ "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc",
+ "src/trace_processor/importers/gzip/gzip_trace_parser.cc",
+ "src/trace_processor/importers/json/json_trace_parser.cc",
+ "src/trace_processor/importers/json/json_trace_tokenizer.cc",
+ "src/trace_processor/importers/json/json_tracker.cc",
+ "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",
+ "src/trace_processor/importers/proto/heap_graph_module.cc",
+ "src/trace_processor/importers/proto/heap_graph_tracker.cc",
+ "src/trace_processor/importers/proto/system_probes_module.cc",
+ "src/trace_processor/importers/proto/system_probes_parser.cc",
+ "src/trace_processor/importers/proto/vulkan_memory_tracker.cc",
+ "src/trace_processor/importers/syscalls/syscall_tracker.cc",
+ "src/trace_processor/importers/systrace/systrace_line_parser.cc",
+ "src/trace_processor/importers/systrace/systrace_line_tokenizer.cc",
+ "src/trace_processor/importers/systrace/systrace_parser.cc",
+ "src/trace_processor/importers/systrace/systrace_trace_parser.cc",
+ ],
}
// GN: //src/trace_processor:storage_minimal
filegroup {
- name: "perfetto_src_trace_processor_storage_minimal",
- srcs: [
- "src/trace_processor/forwarding_trace_parser.cc",
- "src/trace_processor/importers/default_modules.cc",
- "src/trace_processor/importers/ftrace/ftrace_module.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/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",
- "src/trace_processor/trace_sorter.cc",
- "src/trace_processor/virtual_destructors.cc",
- ],
+ name: "perfetto_src_trace_processor_storage_minimal",
+ srcs: [
+ "src/trace_processor/forwarding_trace_parser.cc",
+ "src/trace_processor/importers/default_modules.cc",
+ "src/trace_processor/importers/ftrace/ftrace_module.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/flamegraph_construction_algorithms.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",
+ "src/trace_processor/trace_sorter.cc",
+ "src/trace_processor/virtual_destructors.cc",
+ ],
}
// GN: //src/trace_processor/storage:storage
filegroup {
- name: "perfetto_src_trace_processor_storage_storage",
- srcs: [
- "src/trace_processor/storage/trace_storage.cc",
- ],
+ name: "perfetto_src_trace_processor_storage_storage",
+ srcs: [
+ "src/trace_processor/storage/trace_storage.cc",
+ ],
}
// GN: //src/trace_processor/tables:tables
filegroup {
- name: "perfetto_src_trace_processor_tables_tables",
- srcs: [
- "src/trace_processor/tables/table_destructors.cc",
- ],
+ name: "perfetto_src_trace_processor_tables_tables",
+ srcs: [
+ "src/trace_processor/tables/table_destructors.cc",
+ ],
}
// GN: //src/trace_processor/tables:unittests
filegroup {
- name: "perfetto_src_trace_processor_tables_unittests",
- srcs: [
- "src/trace_processor/tables/macros_unittest.cc",
- ],
+ name: "perfetto_src_trace_processor_tables_unittests",
+ srcs: [
+ "src/trace_processor/tables/macros_unittest.cc",
+ ],
}
// GN: //src/trace_processor/types:types
filegroup {
- name: "perfetto_src_trace_processor_types_types",
- srcs: [
- "src/trace_processor/types/destructible.cc",
- "src/trace_processor/types/gfp_flags.cc",
- "src/trace_processor/types/task_state.cc",
- "src/trace_processor/types/variadic.cc",
- ],
+ name: "perfetto_src_trace_processor_types_types",
+ srcs: [
+ "src/trace_processor/types/destructible.cc",
+ "src/trace_processor/types/gfp_flags.cc",
+ "src/trace_processor/types/task_state.cc",
+ "src/trace_processor/types/variadic.cc",
+ ],
}
// GN: //src/trace_processor/types:unittests
filegroup {
- name: "perfetto_src_trace_processor_types_unittests",
- srcs: [
- "src/trace_processor/types/task_state_unittests.cc",
- ],
+ name: "perfetto_src_trace_processor_types_unittests",
+ srcs: [
+ "src/trace_processor/types/task_state_unittests.cc",
+ ],
}
// GN: //src/trace_processor:unittests
filegroup {
- name: "perfetto_src_trace_processor_unittests",
- 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/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",
- "src/trace_processor/trace_sorter_unittest.cc",
- ],
+ name: "perfetto_src_trace_processor_unittests",
+ srcs: [
+ "src/trace_processor/dynamic/experimental_counter_dur_generator_unittest.cc",
+ "src/trace_processor/dynamic/experimental_flat_slice_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/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",
+ "src/trace_processor/trace_sorter_unittest.cc",
+ ],
}
// GN: //src/trace_processor/util:descriptors
filegroup {
- name: "perfetto_src_trace_processor_util_descriptors",
- srcs: [
- "src/trace_processor/util/descriptors.cc",
- ],
+ name: "perfetto_src_trace_processor_util_descriptors",
+ srcs: [
+ "src/trace_processor/util/descriptors.cc",
+ ],
}
// GN: //src/trace_processor/util:gzip
filegroup {
- name: "perfetto_src_trace_processor_util_gzip",
- srcs: [
- "src/trace_processor/util/gzip_utils.cc",
- ],
+ name: "perfetto_src_trace_processor_util_gzip",
+ srcs: [
+ "src/trace_processor/util/gzip_utils.cc",
+ ],
}
// GN: //src/trace_processor/util:interned_message_view
filegroup {
- name: "perfetto_src_trace_processor_util_interned_message_view",
+ name: "perfetto_src_trace_processor_util_interned_message_view",
}
// 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/debug_annotation_parser.cc",
- "src/trace_processor/util/proto_to_args_parser.cc",
- ],
+ name: "perfetto_src_trace_processor_util_proto_to_args_parser",
+ srcs: [
+ "src/trace_processor/util/debug_annotation_parser.cc",
+ "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",
- srcs: [
- "src/trace_processor/util/protozero_to_text.cc",
- ],
+ name: "perfetto_src_trace_processor_util_protozero_to_text",
+ srcs: [
+ "src/trace_processor/util/protozero_to_text.cc",
+ ],
}
// GN: //src/trace_processor/util:trace_blob_view
filegroup {
- name: "perfetto_src_trace_processor_util_trace_blob_view",
+ name: "perfetto_src_trace_processor_util_trace_blob_view",
}
// GN: //src/trace_processor/util:unittests
filegroup {
- name: "perfetto_src_trace_processor_util_unittests",
- srcs: [
- "src/trace_processor/util/debug_annotation_parser_unittest.cc",
- "src/trace_processor/util/proto_to_args_parser_unittest.cc",
- "src/trace_processor/util/protozero_to_text_unittests.cc",
- ],
+ name: "perfetto_src_trace_processor_util_unittests",
+ srcs: [
+ "src/trace_processor/util/debug_annotation_parser_unittest.cc",
+ "src/trace_processor/util/proto_to_args_parser_unittest.cc",
+ "src/trace_processor/util/protozero_to_text_unittests.cc",
+ ],
}
// GN: //src/trace_processor/util:util
filegroup {
- name: "perfetto_src_trace_processor_util_util",
+ name: "perfetto_src_trace_processor_util_util",
}
// GN: //src/traced/probes/android_log:android_log
filegroup {
- name: "perfetto_src_traced_probes_android_log_android_log",
- srcs: [
- "src/traced/probes/android_log/android_log_data_source.cc",
- ],
+ name: "perfetto_src_traced_probes_android_log_android_log",
+ srcs: [
+ "src/traced/probes/android_log/android_log_data_source.cc",
+ ],
}
// GN: //src/traced/probes/android_log:unittests
filegroup {
- name: "perfetto_src_traced_probes_android_log_unittests",
- srcs: [
- "src/traced/probes/android_log/android_log_data_source_unittest.cc",
- ],
+ name: "perfetto_src_traced_probes_android_log_unittests",
+ srcs: [
+ "src/traced/probes/android_log/android_log_data_source_unittest.cc",
+ ],
}
// GN: //src/traced/probes/common:common
filegroup {
- name: "perfetto_src_traced_probes_common_common",
- srcs: [
- "src/traced/probes/common/cpu_freq_info.cc",
- ],
+ name: "perfetto_src_traced_probes_common_common",
+ srcs: [
+ "src/traced/probes/common/cpu_freq_info.cc",
+ ],
}
// GN: //src/traced/probes/common:test_support
filegroup {
- name: "perfetto_src_traced_probes_common_test_support",
- srcs: [
- "src/traced/probes/common/cpu_freq_info_for_testing.cc",
- ],
+ name: "perfetto_src_traced_probes_common_test_support",
+ srcs: [
+ "src/traced/probes/common/cpu_freq_info_for_testing.cc",
+ ],
}
// GN: //src/traced/probes/common:unittests
filegroup {
- name: "perfetto_src_traced_probes_common_unittests",
- srcs: [
- "src/traced/probes/common/cpu_freq_info_unittest.cc",
- ],
+ name: "perfetto_src_traced_probes_common_unittests",
+ srcs: [
+ "src/traced/probes/common/cpu_freq_info_unittest.cc",
+ ],
}
// GN: //src/traced/probes:data_source
filegroup {
- name: "perfetto_src_traced_probes_data_source",
- srcs: [
- "src/traced/probes/probes_data_source.cc",
- ],
+ name: "perfetto_src_traced_probes_data_source",
+ srcs: [
+ "src/traced/probes/probes_data_source.cc",
+ ],
}
// GN: //src/traced/probes/filesystem:filesystem
filegroup {
- name: "perfetto_src_traced_probes_filesystem_filesystem",
- srcs: [
- "src/traced/probes/filesystem/file_scanner.cc",
- "src/traced/probes/filesystem/fs_mount.cc",
- "src/traced/probes/filesystem/inode_file_data_source.cc",
- "src/traced/probes/filesystem/lru_inode_cache.cc",
- "src/traced/probes/filesystem/prefix_finder.cc",
- "src/traced/probes/filesystem/range_tree.cc",
- ],
+ name: "perfetto_src_traced_probes_filesystem_filesystem",
+ srcs: [
+ "src/traced/probes/filesystem/file_scanner.cc",
+ "src/traced/probes/filesystem/fs_mount.cc",
+ "src/traced/probes/filesystem/inode_file_data_source.cc",
+ "src/traced/probes/filesystem/lru_inode_cache.cc",
+ "src/traced/probes/filesystem/prefix_finder.cc",
+ "src/traced/probes/filesystem/range_tree.cc",
+ ],
}
// GN: //src/traced/probes/filesystem:unittests
filegroup {
- name: "perfetto_src_traced_probes_filesystem_unittests",
- srcs: [
- "src/traced/probes/filesystem/file_scanner_unittest.cc",
- "src/traced/probes/filesystem/fs_mount_unittest.cc",
- "src/traced/probes/filesystem/inode_file_data_source_unittest.cc",
- "src/traced/probes/filesystem/lru_inode_cache_unittest.cc",
- "src/traced/probes/filesystem/prefix_finder_unittest.cc",
- "src/traced/probes/filesystem/range_tree_unittest.cc",
- ],
+ name: "perfetto_src_traced_probes_filesystem_unittests",
+ srcs: [
+ "src/traced/probes/filesystem/file_scanner_unittest.cc",
+ "src/traced/probes/filesystem/fs_mount_unittest.cc",
+ "src/traced/probes/filesystem/inode_file_data_source_unittest.cc",
+ "src/traced/probes/filesystem/lru_inode_cache_unittest.cc",
+ "src/traced/probes/filesystem/prefix_finder_unittest.cc",
+ "src/traced/probes/filesystem/range_tree_unittest.cc",
+ ],
}
// GN: //src/traced/probes/ftrace/format_parser:format_parser
filegroup {
- name: "perfetto_src_traced_probes_ftrace_format_parser_format_parser",
- srcs: [
- "src/traced/probes/ftrace/format_parser/format_parser.cc",
- ],
+ name: "perfetto_src_traced_probes_ftrace_format_parser_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",
- ],
+ name: "perfetto_src_traced_probes_ftrace_format_parser_unittests",
+ srcs: [
+ "src/traced/probes/ftrace/format_parser/format_parser_unittest.cc",
+ ],
}
// GN: //src/traced/probes/ftrace:ftrace
filegroup {
- name: "perfetto_src_traced_probes_ftrace_ftrace",
- srcs: [
- "src/traced/probes/ftrace/atrace_hal_wrapper.cc",
- "src/traced/probes/ftrace/atrace_wrapper.cc",
- "src/traced/probes/ftrace/compact_sched.cc",
- "src/traced/probes/ftrace/cpu_reader.cc",
- "src/traced/probes/ftrace/cpu_stats_parser.cc",
- "src/traced/probes/ftrace/discover_vendor_tracepoints.cc",
- "src/traced/probes/ftrace/event_info.cc",
- "src/traced/probes/ftrace/event_info_constants.cc",
- "src/traced/probes/ftrace/ftrace_config_muxer.cc",
- "src/traced/probes/ftrace/ftrace_config_utils.cc",
- "src/traced/probes/ftrace/ftrace_controller.cc",
- "src/traced/probes/ftrace/ftrace_data_source.cc",
- "src/traced/probes/ftrace/ftrace_stats.cc",
- "src/traced/probes/ftrace/printk_formats_parser.cc",
- "src/traced/probes/ftrace/proto_translation_table.cc",
- ],
+ name: "perfetto_src_traced_probes_ftrace_ftrace",
+ srcs: [
+ "src/traced/probes/ftrace/atrace_hal_wrapper.cc",
+ "src/traced/probes/ftrace/atrace_wrapper.cc",
+ "src/traced/probes/ftrace/compact_sched.cc",
+ "src/traced/probes/ftrace/cpu_reader.cc",
+ "src/traced/probes/ftrace/cpu_stats_parser.cc",
+ "src/traced/probes/ftrace/discover_vendor_tracepoints.cc",
+ "src/traced/probes/ftrace/event_info.cc",
+ "src/traced/probes/ftrace/event_info_constants.cc",
+ "src/traced/probes/ftrace/ftrace_config_muxer.cc",
+ "src/traced/probes/ftrace/ftrace_config_utils.cc",
+ "src/traced/probes/ftrace/ftrace_controller.cc",
+ "src/traced/probes/ftrace/ftrace_data_source.cc",
+ "src/traced/probes/ftrace/ftrace_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",
- ],
+ name: "perfetto_src_traced_probes_ftrace_ftrace_procfs",
+ srcs: [
+ "src/traced/probes/ftrace/ftrace_procfs.cc",
+ ],
}
// GN: //src/traced/probes/ftrace:integrationtests
filegroup {
- name: "perfetto_src_traced_probes_ftrace_integrationtests",
- srcs: [
- "src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc",
- ],
+ name: "perfetto_src_traced_probes_ftrace_integrationtests",
+ srcs: [
+ "src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc",
+ ],
}
// GN: //src/traced/probes/ftrace:test_messages_cpp
genrule {
- name: "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen",
- srcs: [
- "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.gen.cc",
- ],
+ name: "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen",
+ srcs: [
+ "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.gen.cc",
+ ],
}
// GN: //src/traced/probes/ftrace:test_messages_cpp
genrule {
- name: "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen_headers",
- srcs: [
- "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.gen.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen_headers",
+ srcs: [
+ "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.gen.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //src/traced/probes/ftrace:test_messages_lite
genrule {
- name: "perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
- srcs: [
- "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.pb.cc",
- ],
+ name: "perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
+ srcs: [
+ "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.pb.cc",
+ ],
}
// GN: //src/traced/probes/ftrace:test_messages_lite
genrule {
- name: "perfetto_src_traced_probes_ftrace_test_messages_lite_gen_headers",
- srcs: [
- "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_src_traced_probes_ftrace_test_messages_lite_gen_headers",
+ srcs: [
+ "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //src/traced/probes/ftrace:test_messages_zero
genrule {
- name: "perfetto_src_traced_probes_ftrace_test_messages_zero_gen",
- srcs: [
- "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.pbzero.cc",
- ],
+ name: "perfetto_src_traced_probes_ftrace_test_messages_zero_gen",
+ srcs: [
+ "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.pbzero.cc",
+ ],
}
// GN: //src/traced/probes/ftrace:test_messages_zero
genrule {
- name: "perfetto_src_traced_probes_ftrace_test_messages_zero_gen_headers",
- srcs: [
- "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.pbzero.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
+ name: "perfetto_src_traced_probes_ftrace_test_messages_zero_gen_headers",
+ srcs: [
+ "src/traced/probes/ftrace/test/test_messages.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/src/traced/probes/ftrace/test/test_messages.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
}
// GN: //src/traced/probes/ftrace:test_support
filegroup {
- name: "perfetto_src_traced_probes_ftrace_test_support",
- srcs: [
- "src/traced/probes/ftrace/test/cpu_reader_support.cc",
- ],
+ name: "perfetto_src_traced_probes_ftrace_test_support",
+ srcs: [
+ "src/traced/probes/ftrace/test/cpu_reader_support.cc",
+ ],
}
// GN: //src/traced/probes/ftrace:unittests
filegroup {
- name: "perfetto_src_traced_probes_ftrace_unittests",
- srcs: [
- "src/traced/probes/ftrace/cpu_reader_unittest.cc",
- "src/traced/probes/ftrace/cpu_stats_parser_unittest.cc",
- "src/traced/probes/ftrace/discover_vendor_tracepoints_unittest.cc",
- "src/traced/probes/ftrace/event_info_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",
- ],
+ name: "perfetto_src_traced_probes_ftrace_unittests",
+ srcs: [
+ "src/traced/probes/ftrace/cpu_reader_unittest.cc",
+ "src/traced/probes/ftrace/cpu_stats_parser_unittest.cc",
+ "src/traced/probes/ftrace/discover_vendor_tracepoints_unittest.cc",
+ "src/traced/probes/ftrace/event_info_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",
+ ],
}
// GN: //src/traced/probes/initial_display_state:initial_display_state
filegroup {
- name: "perfetto_src_traced_probes_initial_display_state_initial_display_state",
- srcs: [
- "src/traced/probes/initial_display_state/initial_display_state_data_source.cc",
- ],
+ name: "perfetto_src_traced_probes_initial_display_state_initial_display_state",
+ srcs: [
+ "src/traced/probes/initial_display_state/initial_display_state_data_source.cc",
+ ],
}
// GN: //src/traced/probes/initial_display_state:unittests
filegroup {
- name: "perfetto_src_traced_probes_initial_display_state_unittests",
- srcs: [
- "src/traced/probes/initial_display_state/initial_display_state_data_source_unittest.cc",
- ],
+ name: "perfetto_src_traced_probes_initial_display_state_unittests",
+ srcs: [
+ "src/traced/probes/initial_display_state/initial_display_state_data_source_unittest.cc",
+ ],
}
// GN: //src/traced/probes/metatrace:metatrace
filegroup {
- name: "perfetto_src_traced_probes_metatrace_metatrace",
- srcs: [
- "src/traced/probes/metatrace/metatrace_data_source.cc",
- ],
+ name: "perfetto_src_traced_probes_metatrace_metatrace",
+ srcs: [
+ "src/traced/probes/metatrace/metatrace_data_source.cc",
+ ],
}
// GN: //src/traced/probes/packages_list:packages_list
filegroup {
- name: "perfetto_src_traced_probes_packages_list_packages_list",
- srcs: [
- "src/traced/probes/packages_list/packages_list_data_source.cc",
- ],
+ name: "perfetto_src_traced_probes_packages_list_packages_list",
+ srcs: [
+ "src/traced/probes/packages_list/packages_list_data_source.cc",
+ ],
}
// GN: //src/traced/probes/packages_list:packages_list_parser
filegroup {
- name: "perfetto_src_traced_probes_packages_list_packages_list_parser",
- srcs: [
- "src/traced/probes/packages_list/packages_list_parser.cc",
- ],
+ 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",
- ],
+ name: "perfetto_src_traced_probes_packages_list_unittests",
+ srcs: [
+ "src/traced/probes/packages_list/packages_list_unittest.cc",
+ ],
}
// GN: //src/traced/probes/power:power
filegroup {
- name: "perfetto_src_traced_probes_power_power",
- srcs: [
- "src/traced/probes/power/android_power_data_source.cc",
- ],
+ name: "perfetto_src_traced_probes_power_power",
+ srcs: [
+ "src/traced/probes/power/android_power_data_source.cc",
+ ],
}
// GN: //src/traced/probes:probes
filegroup {
- name: "perfetto_src_traced_probes_probes",
- srcs: [
- "src/traced/probes/probes.cc",
- ],
+ name: "perfetto_src_traced_probes_probes",
+ srcs: [
+ "src/traced/probes/probes.cc",
+ ],
}
// GN: //src/traced/probes:probes_src
filegroup {
- name: "perfetto_src_traced_probes_probes_src",
- srcs: [
- "src/traced/probes/kmem_activity_trigger.cc",
- "src/traced/probes/probes_producer.cc",
- ],
+ name: "perfetto_src_traced_probes_probes_src",
+ srcs: [
+ "src/traced/probes/kmem_activity_trigger.cc",
+ "src/traced/probes/probes_producer.cc",
+ ],
}
// GN: //src/traced/probes/ps:ps
filegroup {
- name: "perfetto_src_traced_probes_ps_ps",
- srcs: [
- "src/traced/probes/ps/process_stats_data_source.cc",
- ],
+ name: "perfetto_src_traced_probes_ps_ps",
+ srcs: [
+ "src/traced/probes/ps/process_stats_data_source.cc",
+ ],
}
// GN: //src/traced/probes/ps:unittests
filegroup {
- name: "perfetto_src_traced_probes_ps_unittests",
- srcs: [
- "src/traced/probes/ps/process_stats_data_source_unittest.cc",
- ],
+ name: "perfetto_src_traced_probes_ps_unittests",
+ srcs: [
+ "src/traced/probes/ps/process_stats_data_source_unittest.cc",
+ ],
}
// GN: //src/traced/probes/sys_stats:sys_stats
filegroup {
- name: "perfetto_src_traced_probes_sys_stats_sys_stats",
- srcs: [
- "src/traced/probes/sys_stats/sys_stats_data_source.cc",
- ],
+ name: "perfetto_src_traced_probes_sys_stats_sys_stats",
+ srcs: [
+ "src/traced/probes/sys_stats/sys_stats_data_source.cc",
+ ],
}
// GN: //src/traced/probes/sys_stats:unittests
filegroup {
- name: "perfetto_src_traced_probes_sys_stats_unittests",
- srcs: [
- "src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc",
- ],
+ name: "perfetto_src_traced_probes_sys_stats_unittests",
+ srcs: [
+ "src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc",
+ ],
}
// GN: //src/traced/probes/system_info:system_info
filegroup {
- name: "perfetto_src_traced_probes_system_info_system_info",
- srcs: [
- "src/traced/probes/system_info/system_info_data_source.cc",
- ],
+ name: "perfetto_src_traced_probes_system_info_system_info",
+ srcs: [
+ "src/traced/probes/system_info/system_info_data_source.cc",
+ ],
}
// GN: //src/traced/probes/system_info:unittests
filegroup {
- name: "perfetto_src_traced_probes_system_info_unittests",
- srcs: [
- "src/traced/probes/system_info/system_info_data_source_unittest.cc",
- ],
+ name: "perfetto_src_traced_probes_system_info_unittests",
+ srcs: [
+ "src/traced/probes/system_info/system_info_data_source_unittest.cc",
+ ],
}
// GN: //src/traced/probes:unittests
filegroup {
- name: "perfetto_src_traced_probes_unittests",
+ name: "perfetto_src_traced_probes_unittests",
}
// GN: //src/traced/service:service
filegroup {
- name: "perfetto_src_traced_service_service",
- srcs: [
- "src/traced/service/builtin_producer.cc",
- "src/traced/service/service.cc",
- ],
+ name: "perfetto_src_traced_service_service",
+ srcs: [
+ "src/traced/service/builtin_producer.cc",
+ "src/traced/service/service.cc",
+ ],
}
// GN: //src/traced/service:unittests
filegroup {
- name: "perfetto_src_traced_service_unittests",
- srcs: [
- "src/traced/service/builtin_producer_unittest.cc",
- ],
+ name: "perfetto_src_traced_service_unittests",
+ srcs: [
+ "src/traced/service/builtin_producer_unittest.cc",
+ ],
}
// GN: //src/tracing:client_api_without_backends
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",
- ],
+ 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",
+ ],
}
// GN: //src/tracing:common
filegroup {
- name: "perfetto_src_tracing_common",
- srcs: [
- "src/tracing/trace_writer_base.cc",
- ],
+ name: "perfetto_src_tracing_common",
+ srcs: [
+ "src/tracing/trace_writer_base.cc",
+ ],
}
// GN: //src/tracing/consumer_api_deprecated:consumer_api_deprecated
filegroup {
- name: "perfetto_src_tracing_consumer_api_deprecated_consumer_api_deprecated",
- srcs: [
- "src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc",
- ],
+ name: "perfetto_src_tracing_consumer_api_deprecated_consumer_api_deprecated",
+ srcs: [
+ "src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc",
+ ],
}
// GN: //src/tracing/core:core
filegroup {
- name: "perfetto_src_tracing_core_core",
- srcs: [
- "src/tracing/core/id_allocator.cc",
- "src/tracing/core/null_trace_writer.cc",
- "src/tracing/core/shared_memory_abi.cc",
- "src/tracing/core/shared_memory_arbiter_impl.cc",
- "src/tracing/core/trace_packet.cc",
- "src/tracing/core/trace_writer_impl.cc",
- "src/tracing/core/virtual_destructors.cc",
- ],
+ name: "perfetto_src_tracing_core_core",
+ srcs: [
+ "src/tracing/core/id_allocator.cc",
+ "src/tracing/core/null_trace_writer.cc",
+ "src/tracing/core/shared_memory_abi.cc",
+ "src/tracing/core/shared_memory_arbiter_impl.cc",
+ "src/tracing/core/trace_packet.cc",
+ "src/tracing/core/trace_writer_impl.cc",
+ "src/tracing/core/virtual_destructors.cc",
+ ],
}
// GN: //src/tracing/core:service
filegroup {
- name: "perfetto_src_tracing_core_service",
- srcs: [
- "src/tracing/core/metatrace_writer.cc",
- "src/tracing/core/packet_stream_validator.cc",
- "src/tracing/core/trace_buffer.cc",
- "src/tracing/core/tracing_service_impl.cc",
- ],
+ name: "perfetto_src_tracing_core_service",
+ srcs: [
+ "src/tracing/core/metatrace_writer.cc",
+ "src/tracing/core/packet_stream_validator.cc",
+ "src/tracing/core/trace_buffer.cc",
+ "src/tracing/core/tracing_service_impl.cc",
+ ],
}
// GN: //src/tracing/core:test_support
filegroup {
- name: "perfetto_src_tracing_core_test_support",
- srcs: [
- "src/tracing/core/trace_writer_for_testing.cc",
- ],
+ name: "perfetto_src_tracing_core_test_support",
+ srcs: [
+ "src/tracing/core/trace_writer_for_testing.cc",
+ ],
}
// GN: //src/tracing/core:unittests
filegroup {
- name: "perfetto_src_tracing_core_unittests",
- srcs: [
- "src/tracing/core/id_allocator_unittest.cc",
- "src/tracing/core/null_trace_writer_unittest.cc",
- "src/tracing/core/packet_stream_validator_unittest.cc",
- "src/tracing/core/patch_list_unittest.cc",
- "src/tracing/core/shared_memory_abi_unittest.cc",
- "src/tracing/core/shared_memory_arbiter_impl_unittest.cc",
- "src/tracing/core/trace_buffer_unittest.cc",
- "src/tracing/core/trace_packet_unittest.cc",
- "src/tracing/core/trace_writer_impl_unittest.cc",
- "src/tracing/core/tracing_service_impl_unittest.cc",
- ],
+ name: "perfetto_src_tracing_core_unittests",
+ srcs: [
+ "src/tracing/core/id_allocator_unittest.cc",
+ "src/tracing/core/null_trace_writer_unittest.cc",
+ "src/tracing/core/packet_stream_validator_unittest.cc",
+ "src/tracing/core/patch_list_unittest.cc",
+ "src/tracing/core/shared_memory_abi_unittest.cc",
+ "src/tracing/core/shared_memory_arbiter_impl_unittest.cc",
+ "src/tracing/core/trace_buffer_unittest.cc",
+ "src/tracing/core/trace_packet_unittest.cc",
+ "src/tracing/core/trace_writer_impl_unittest.cc",
+ "src/tracing/core/tracing_service_impl_unittest.cc",
+ ],
}
// GN: //src/tracing:in_process_backend
filegroup {
- name: "perfetto_src_tracing_in_process_backend",
- srcs: [
- "src/tracing/internal/in_process_tracing_backend.cc",
- ],
+ name: "perfetto_src_tracing_in_process_backend",
+ srcs: [
+ "src/tracing/internal/in_process_tracing_backend.cc",
+ ],
}
// GN: //src/tracing/ipc:common
filegroup {
- name: "perfetto_src_tracing_ipc_common",
- srcs: [
- "src/tracing/ipc/default_socket.cc",
- "src/tracing/ipc/memfd.cc",
- "src/tracing/ipc/posix_shared_memory.cc",
- "src/tracing/ipc/shared_memory_windows.cc",
- ],
+ name: "perfetto_src_tracing_ipc_common",
+ srcs: [
+ "src/tracing/ipc/default_socket.cc",
+ "src/tracing/ipc/memfd.cc",
+ "src/tracing/ipc/posix_shared_memory.cc",
+ "src/tracing/ipc/shared_memory_windows.cc",
+ ],
}
// GN: //src/tracing/ipc/consumer:consumer
filegroup {
- name: "perfetto_src_tracing_ipc_consumer_consumer",
- srcs: [
- "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
- ],
+ name: "perfetto_src_tracing_ipc_consumer_consumer",
+ srcs: [
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
+ ],
}
// GN: //src/tracing/ipc/producer:producer
filegroup {
- name: "perfetto_src_tracing_ipc_producer_producer",
- srcs: [
- "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
- ],
+ name: "perfetto_src_tracing_ipc_producer_producer",
+ srcs: [
+ "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
+ ],
}
// GN: //src/tracing/ipc/service:service
filegroup {
- name: "perfetto_src_tracing_ipc_service_service",
- srcs: [
- "src/tracing/ipc/service/consumer_ipc_service.cc",
- "src/tracing/ipc/service/producer_ipc_service.cc",
- "src/tracing/ipc/service/service_ipc_host_impl.cc",
- ],
+ name: "perfetto_src_tracing_ipc_service_service",
+ srcs: [
+ "src/tracing/ipc/service/consumer_ipc_service.cc",
+ "src/tracing/ipc/service/producer_ipc_service.cc",
+ "src/tracing/ipc/service/service_ipc_host_impl.cc",
+ ],
}
// GN: //src/tracing/ipc:unittests
filegroup {
- name: "perfetto_src_tracing_ipc_unittests",
- srcs: [
- "src/tracing/ipc/posix_shared_memory_unittest.cc",
- ],
+ name: "perfetto_src_tracing_ipc_unittests",
+ srcs: [
+ "src/tracing/ipc/posix_shared_memory_unittest.cc",
+ ],
}
// GN: //src/tracing:platform_impl
filegroup {
- name: "perfetto_src_tracing_platform_impl",
- srcs: [
- "src/tracing/platform_posix.cc",
- "src/tracing/platform_windows.cc",
- ],
+ name: "perfetto_src_tracing_platform_impl",
+ srcs: [
+ "src/tracing/platform_posix.cc",
+ "src/tracing/platform_windows.cc",
+ ],
}
// GN: //src/tracing:system_backend
filegroup {
- name: "perfetto_src_tracing_system_backend",
- srcs: [
- "src/tracing/internal/system_tracing_backend.cc",
- ],
+ name: "perfetto_src_tracing_system_backend",
+ srcs: [
+ "src/tracing/internal/system_tracing_backend.cc",
+ ],
}
// GN: //src/tracing/test:api_test_support
filegroup {
- name: "perfetto_src_tracing_test_api_test_support",
- srcs: [
- "src/tracing/test/api_test_support.cc",
- ],
+ name: "perfetto_src_tracing_test_api_test_support",
+ srcs: [
+ "src/tracing/test/api_test_support.cc",
+ ],
}
// GN: //src/tracing/test:client_api_integrationtests
filegroup {
- name: "perfetto_src_tracing_test_client_api_integrationtests",
- srcs: [
- "src/tracing/test/api_integrationtest.cc",
- "src/tracing/test/tracing_module.cc",
- "src/tracing/test/tracing_module2.cc",
- ],
+ name: "perfetto_src_tracing_test_client_api_integrationtests",
+ srcs: [
+ "src/tracing/test/api_integrationtest.cc",
+ "src/tracing/test/tracing_module.cc",
+ "src/tracing/test/tracing_module2.cc",
+ ],
}
// GN: //src/tracing/test:test_support
filegroup {
- name: "perfetto_src_tracing_test_test_support",
- srcs: [
- "src/tracing/test/aligned_buffer_test.cc",
- "src/tracing/test/fake_packet.cc",
- "src/tracing/test/mock_consumer.cc",
- "src/tracing/test/mock_producer.cc",
- "src/tracing/test/test_shared_memory.cc",
- "src/tracing/test/traced_value_test_support.cc",
- ],
+ name: "perfetto_src_tracing_test_test_support",
+ srcs: [
+ "src/tracing/test/aligned_buffer_test.cc",
+ "src/tracing/test/fake_packet.cc",
+ "src/tracing/test/mock_consumer.cc",
+ "src/tracing/test/mock_producer.cc",
+ "src/tracing/test/test_shared_memory.cc",
+ "src/tracing/test/traced_value_test_support.cc",
+ ],
}
// GN: //src/tracing/test:tracing_integration_test
filegroup {
- name: "perfetto_src_tracing_test_tracing_integration_test",
- srcs: [
- "src/tracing/test/platform_unittest.cc",
- "src/tracing/test/tracing_integration_test.cc",
- ],
+ 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",
- ],
+ 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",
- srcs: [
- "test/end_to_end_integrationtest.cc",
- ],
+ name: "perfetto_test_end_to_end_integrationtests",
+ srcs: [
+ "test/end_to_end_integrationtest.cc",
+ ],
}
// GN: //test:test_helper
filegroup {
- name: "perfetto_test_test_helper",
- srcs: [
- "test/android_test_utils.cc",
- "test/fake_producer.cc",
- "test/test_helper.cc",
- ],
+ name: "perfetto_test_test_helper",
+ srcs: [
+ "test/android_test_utils.cc",
+ "test/fake_producer.cc",
+ "test/test_helper.cc",
+ ],
}
// GN: //tools/sanitizers_unittests:sanitizers_unittests
filegroup {
- name: "perfetto_tools_sanitizers_unittests_sanitizers_unittests",
- srcs: [
- "tools/sanitizers_unittests/sanitizers_unittest.cc",
- ],
+ name: "perfetto_tools_sanitizers_unittests_sanitizers_unittests",
+ srcs: [
+ "tools/sanitizers_unittests/sanitizers_unittest.cc",
+ ],
}
// GN: //tools/trace_to_text:common
filegroup {
- name: "perfetto_tools_trace_to_text_common",
- srcs: [
- "tools/trace_to_text/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",
- ],
+ name: "perfetto_tools_trace_to_text_common",
+ srcs: [
+ "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",
+ ],
}
// GN: //tools/trace_to_text:full
filegroup {
- name: "perfetto_tools_trace_to_text_full",
- srcs: [
- "tools/trace_to_text/proto_full_utils.cc",
- "tools/trace_to_text/trace_to_text.cc",
- ],
+ name: "perfetto_tools_trace_to_text_full",
+ srcs: [
+ "tools/trace_to_text/proto_full_utils.cc",
+ "tools/trace_to_text/trace_to_text.cc",
+ ],
}
// GN: //tools/trace_to_text:gen_cc_trace_descriptor
genrule {
- name: "perfetto_tools_trace_to_text_gen_cc_trace_descriptor",
- srcs: [
- ":perfetto_protos_perfetto_trace_descriptor",
- ],
- cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
- out: [
- "tools/trace_to_text/trace.descriptor.h",
- ],
- tool_files: [
- "tools/gen_cc_proto_descriptor.py",
- ],
+ name: "perfetto_tools_trace_to_text_gen_cc_trace_descriptor",
+ srcs: [
+ ":perfetto_protos_perfetto_trace_descriptor",
+ ],
+ cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
+ out: [
+ "tools/trace_to_text/trace.descriptor.h",
+ ],
+ tool_files: [
+ "tools/gen_cc_proto_descriptor.py",
+ ],
}
// GN: //tools/trace_to_text:pprofbuilder
filegroup {
- name: "perfetto_tools_trace_to_text_pprofbuilder",
- srcs: [
- "tools/trace_to_text/pprof_builder.cc",
- ],
+ name: "perfetto_tools_trace_to_text_pprofbuilder",
+ srcs: [
+ "tools/trace_to_text/pprof_builder.cc",
+ ],
}
// GN: //tools/trace_to_text:utils
filegroup {
- name: "perfetto_tools_trace_to_text_utils",
- srcs: [
- "tools/trace_to_text/utils.cc",
- ],
+ name: "perfetto_tools_trace_to_text_utils",
+ srcs: [
+ "tools/trace_to_text/utils.cc",
+ ],
}
// GN: //protos/perfetto/trace:perfetto_trace_protos
cc_library_static {
- name: "perfetto_trace_protos",
- srcs: [
- ":perfetto_protos_perfetto_common_lite_gen",
- ":perfetto_protos_perfetto_config_android_lite_gen",
- ":perfetto_protos_perfetto_config_ftrace_lite_gen",
- ":perfetto_protos_perfetto_config_gpu_lite_gen",
- ":perfetto_protos_perfetto_config_inode_file_lite_gen",
- ":perfetto_protos_perfetto_config_interceptors_lite_gen",
- ":perfetto_protos_perfetto_config_lite_gen",
- ":perfetto_protos_perfetto_config_power_lite_gen",
- ":perfetto_protos_perfetto_config_process_stats_lite_gen",
- ":perfetto_protos_perfetto_config_profiling_lite_gen",
- ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
- ":perfetto_protos_perfetto_config_track_event_lite_gen",
- ":perfetto_protos_perfetto_trace_android_lite_gen",
- ":perfetto_protos_perfetto_trace_chrome_lite_gen",
- ":perfetto_protos_perfetto_trace_filesystem_lite_gen",
- ":perfetto_protos_perfetto_trace_ftrace_lite_gen",
- ":perfetto_protos_perfetto_trace_gpu_lite_gen",
- ":perfetto_protos_perfetto_trace_interned_data_lite_gen",
- ":perfetto_protos_perfetto_trace_minimal_lite_gen",
- ":perfetto_protos_perfetto_trace_non_minimal_lite_gen",
- ":perfetto_protos_perfetto_trace_perfetto_lite_gen",
- ":perfetto_protos_perfetto_trace_power_lite_gen",
- ":perfetto_protos_perfetto_trace_profiling_lite_gen",
- ":perfetto_protos_perfetto_trace_ps_lite_gen",
- ":perfetto_protos_perfetto_trace_sys_stats_lite_gen",
- ":perfetto_protos_perfetto_trace_system_info_lite_gen",
- ":perfetto_protos_perfetto_trace_track_event_lite_gen",
- ],
- shared_libs: [
- "libprotobuf-cpp-lite",
- ],
- host_supported: true,
- 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",
- "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
- "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
- "perfetto_protos_perfetto_config_track_event_lite_gen_headers",
- "perfetto_protos_perfetto_trace_android_lite_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
- "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
- "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
- "perfetto_protos_perfetto_trace_power_lite_gen_headers",
- "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
- "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
- "perfetto_protos_perfetto_trace_sys_stats_lite_gen_headers",
- "perfetto_protos_perfetto_trace_system_info_lite_gen_headers",
- "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
- ],
- export_generated_headers: [
- "perfetto_protos_perfetto_common_lite_gen_headers",
- "perfetto_protos_perfetto_config_android_lite_gen_headers",
- "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
- "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
- "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
- "perfetto_protos_perfetto_config_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",
- "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
- "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
- "perfetto_protos_perfetto_config_track_event_lite_gen_headers",
- "perfetto_protos_perfetto_trace_android_lite_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
- "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
- "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
- "perfetto_protos_perfetto_trace_power_lite_gen_headers",
- "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
- "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
- "perfetto_protos_perfetto_trace_sys_stats_lite_gen_headers",
- "perfetto_protos_perfetto_trace_system_info_lite_gen_headers",
- "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- ],
- apex_available: [
- "//apex_available:platform",
- "com.android.art",
- "com.android.art.debug",
- ],
- min_sdk_version: "S",
+ name: "perfetto_trace_protos",
+ srcs: [
+ ":perfetto_protos_perfetto_common_lite_gen",
+ ":perfetto_protos_perfetto_config_android_lite_gen",
+ ":perfetto_protos_perfetto_config_ftrace_lite_gen",
+ ":perfetto_protos_perfetto_config_gpu_lite_gen",
+ ":perfetto_protos_perfetto_config_inode_file_lite_gen",
+ ":perfetto_protos_perfetto_config_interceptors_lite_gen",
+ ":perfetto_protos_perfetto_config_lite_gen",
+ ":perfetto_protos_perfetto_config_power_lite_gen",
+ ":perfetto_protos_perfetto_config_process_stats_lite_gen",
+ ":perfetto_protos_perfetto_config_profiling_lite_gen",
+ ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
+ ":perfetto_protos_perfetto_config_track_event_lite_gen",
+ ":perfetto_protos_perfetto_trace_android_lite_gen",
+ ":perfetto_protos_perfetto_trace_chrome_lite_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_lite_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_lite_gen",
+ ":perfetto_protos_perfetto_trace_gpu_lite_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_lite_gen",
+ ":perfetto_protos_perfetto_trace_minimal_lite_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_lite_gen",
+ ":perfetto_protos_perfetto_trace_perfetto_lite_gen",
+ ":perfetto_protos_perfetto_trace_power_lite_gen",
+ ":perfetto_protos_perfetto_trace_profiling_lite_gen",
+ ":perfetto_protos_perfetto_trace_ps_lite_gen",
+ ":perfetto_protos_perfetto_trace_sys_stats_lite_gen",
+ ":perfetto_protos_perfetto_trace_system_info_lite_gen",
+ ":perfetto_protos_perfetto_trace_track_event_lite_gen",
+ ],
+ shared_libs: [
+ "libprotobuf-cpp-lite",
+ ],
+ host_supported: true,
+ 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",
+ "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
+ "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
+ "perfetto_protos_perfetto_config_track_event_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_android_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_power_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_sys_stats_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_system_info_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
+ ],
+ export_generated_headers: [
+ "perfetto_protos_perfetto_common_lite_gen_headers",
+ "perfetto_protos_perfetto_config_android_lite_gen_headers",
+ "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
+ "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
+ "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
+ "perfetto_protos_perfetto_config_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",
+ "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
+ "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
+ "perfetto_protos_perfetto_config_track_event_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_android_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_power_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_sys_stats_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_system_info_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.art",
+ "com.android.art.debug",
+ ],
+ min_sdk_version: "S",
}
// GN: //:perfetto_unittests
cc_test {
- name: "perfetto_unittests",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_ext_ipc_ipc",
- ":perfetto_include_perfetto_ext_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_test_test_support",
- ":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",
- ":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_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",
- ":perfetto_src_base_unix_socket",
- ":perfetto_src_ipc_client",
- ":perfetto_src_ipc_common",
- ":perfetto_src_ipc_host",
- ":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_cmd",
- ":perfetto_src_perfetto_cmd_protos_gen",
- ":perfetto_src_perfetto_cmd_trigger_producer",
- ":perfetto_src_perfetto_cmd_unittests",
- ":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_unittests",
- ":perfetto_src_profiling_common_unwind_support",
- ":perfetto_src_profiling_deobfuscator",
- ":perfetto_src_profiling_memory_client",
- ":perfetto_src_profiling_memory_daemon",
- ":perfetto_src_profiling_memory_ring_buffer",
- ":perfetto_src_profiling_memory_ring_buffer_unittests",
- ":perfetto_src_profiling_memory_scoped_spinlock",
- ":perfetto_src_profiling_memory_unittests",
- ":perfetto_src_profiling_memory_wire_protocol",
- ":perfetto_src_profiling_perf_common_types",
- ":perfetto_src_profiling_perf_proc_descriptors",
- ":perfetto_src_profiling_perf_producer",
- ":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_proto_ring_buffer",
- ":perfetto_src_protozero_protozero",
- ":perfetto_src_protozero_testing_messages_cpp_gen",
- ":perfetto_src_protozero_testing_messages_lite_gen",
- ":perfetto_src_protozero_testing_messages_zero_gen",
- ":perfetto_src_protozero_unittests",
- ":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_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_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",
- ":perfetto_src_trace_processor_storage_minimal",
- ":perfetto_src_trace_processor_storage_storage",
- ":perfetto_src_trace_processor_tables_tables",
- ":perfetto_src_trace_processor_tables_unittests",
- ":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_gzip",
- ":perfetto_src_trace_processor_util_interned_message_view",
- ":perfetto_src_trace_processor_util_proto_to_args_parser",
- ":perfetto_src_trace_processor_util_protozero_to_text",
- ":perfetto_src_trace_processor_util_trace_blob_view",
- ":perfetto_src_trace_processor_util_unittests",
- ":perfetto_src_trace_processor_util_util",
- ":perfetto_src_traced_probes_android_log_android_log",
- ":perfetto_src_traced_probes_android_log_unittests",
- ":perfetto_src_traced_probes_common_common",
- ":perfetto_src_traced_probes_common_test_support",
- ":perfetto_src_traced_probes_common_unittests",
- ":perfetto_src_traced_probes_data_source",
- ":perfetto_src_traced_probes_filesystem_filesystem",
- ":perfetto_src_traced_probes_filesystem_unittests",
- ":perfetto_src_traced_probes_ftrace_format_parser_format_parser",
- ":perfetto_src_traced_probes_ftrace_format_parser_unittests",
- ":perfetto_src_traced_probes_ftrace_ftrace",
- ":perfetto_src_traced_probes_ftrace_ftrace_procfs",
- ":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",
- ":perfetto_src_traced_probes_ftrace_test_support",
- ":perfetto_src_traced_probes_ftrace_unittests",
- ":perfetto_src_traced_probes_initial_display_state_initial_display_state",
- ":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",
- ":perfetto_src_traced_probes_ps_ps",
- ":perfetto_src_traced_probes_ps_unittests",
- ":perfetto_src_traced_probes_sys_stats_sys_stats",
- ":perfetto_src_traced_probes_sys_stats_unittests",
- ":perfetto_src_traced_probes_system_info_system_info",
- ":perfetto_src_traced_probes_system_info_unittests",
- ":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",
- ":perfetto_src_tracing_core_test_support",
- ":perfetto_src_tracing_core_unittests",
- ":perfetto_src_tracing_ipc_common",
- ":perfetto_src_tracing_ipc_consumer_consumer",
- ":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: [
- "libgmock",
- "libgtest",
- ],
- whole_static_libs: [
- "perfetto_gtest_logcat_printer",
- ],
- generated_headers: [
- "perfetto_protos_perfetto_common_cpp_gen_headers",
- "perfetto_protos_perfetto_common_lite_gen_headers",
- "perfetto_protos_perfetto_common_zero_gen_headers",
- "perfetto_protos_perfetto_config_android_cpp_gen_headers",
- "perfetto_protos_perfetto_config_android_lite_gen_headers",
- "perfetto_protos_perfetto_config_android_zero_gen_headers",
- "perfetto_protos_perfetto_config_cpp_gen_headers",
- "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
- "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
- "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
- "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
- "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
- "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
- "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
- "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
- "perfetto_protos_perfetto_config_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_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",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_HIDDEN",
- ],
- include_dirs: [
- "bionic/libc/kernel",
- ],
- header_libs: [
- "bionic_libc_platform_headers",
- ],
- data: [
- "src/traced/probes/filesystem/testdata/**/*",
- "src/traced/probes/ftrace/test/data/**/*",
- ],
+ name: "perfetto_unittests",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_ipc_ipc",
+ ":perfetto_include_perfetto_ext_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_test_test_support",
+ ":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",
+ ":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_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",
+ ":perfetto_src_base_unix_socket",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
+ ":perfetto_src_ipc_host",
+ ":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_cmd",
+ ":perfetto_src_perfetto_cmd_protos_gen",
+ ":perfetto_src_perfetto_cmd_trigger_producer",
+ ":perfetto_src_perfetto_cmd_unittests",
+ ":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_unittests",
+ ":perfetto_src_profiling_common_unwind_support",
+ ":perfetto_src_profiling_deobfuscator",
+ ":perfetto_src_profiling_memory_client",
+ ":perfetto_src_profiling_memory_daemon",
+ ":perfetto_src_profiling_memory_ring_buffer",
+ ":perfetto_src_profiling_memory_ring_buffer_unittests",
+ ":perfetto_src_profiling_memory_scoped_spinlock",
+ ":perfetto_src_profiling_memory_unittests",
+ ":perfetto_src_profiling_memory_wire_protocol",
+ ":perfetto_src_profiling_perf_common_types",
+ ":perfetto_src_profiling_perf_proc_descriptors",
+ ":perfetto_src_profiling_perf_producer",
+ ":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_proto_ring_buffer",
+ ":perfetto_src_protozero_protozero",
+ ":perfetto_src_protozero_testing_messages_cpp_gen",
+ ":perfetto_src_protozero_testing_messages_lite_gen",
+ ":perfetto_src_protozero_testing_messages_zero_gen",
+ ":perfetto_src_protozero_unittests",
+ ":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_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_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",
+ ":perfetto_src_trace_processor_storage_minimal",
+ ":perfetto_src_trace_processor_storage_storage",
+ ":perfetto_src_trace_processor_tables_tables",
+ ":perfetto_src_trace_processor_tables_unittests",
+ ":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_gzip",
+ ":perfetto_src_trace_processor_util_interned_message_view",
+ ":perfetto_src_trace_processor_util_proto_to_args_parser",
+ ":perfetto_src_trace_processor_util_protozero_to_text",
+ ":perfetto_src_trace_processor_util_trace_blob_view",
+ ":perfetto_src_trace_processor_util_unittests",
+ ":perfetto_src_trace_processor_util_util",
+ ":perfetto_src_traced_probes_android_log_android_log",
+ ":perfetto_src_traced_probes_android_log_unittests",
+ ":perfetto_src_traced_probes_common_common",
+ ":perfetto_src_traced_probes_common_test_support",
+ ":perfetto_src_traced_probes_common_unittests",
+ ":perfetto_src_traced_probes_data_source",
+ ":perfetto_src_traced_probes_filesystem_filesystem",
+ ":perfetto_src_traced_probes_filesystem_unittests",
+ ":perfetto_src_traced_probes_ftrace_format_parser_format_parser",
+ ":perfetto_src_traced_probes_ftrace_format_parser_unittests",
+ ":perfetto_src_traced_probes_ftrace_ftrace",
+ ":perfetto_src_traced_probes_ftrace_ftrace_procfs",
+ ":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",
+ ":perfetto_src_traced_probes_ftrace_test_support",
+ ":perfetto_src_traced_probes_ftrace_unittests",
+ ":perfetto_src_traced_probes_initial_display_state_initial_display_state",
+ ":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",
+ ":perfetto_src_traced_probes_ps_ps",
+ ":perfetto_src_traced_probes_ps_unittests",
+ ":perfetto_src_traced_probes_sys_stats_sys_stats",
+ ":perfetto_src_traced_probes_sys_stats_unittests",
+ ":perfetto_src_traced_probes_system_info_system_info",
+ ":perfetto_src_traced_probes_system_info_unittests",
+ ":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",
+ ":perfetto_src_tracing_core_test_support",
+ ":perfetto_src_tracing_core_unittests",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":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: [
+ "libgmock",
+ "libgtest",
+ ],
+ whole_static_libs: [
+ "perfetto_gtest_logcat_printer",
+ ],
+ generated_headers: [
+ "perfetto_protos_perfetto_common_cpp_gen_headers",
+ "perfetto_protos_perfetto_common_lite_gen_headers",
+ "perfetto_protos_perfetto_common_zero_gen_headers",
+ "perfetto_protos_perfetto_config_android_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_android_lite_gen_headers",
+ "perfetto_protos_perfetto_config_android_zero_gen_headers",
+ "perfetto_protos_perfetto_config_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
+ "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
+ "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
+ "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
+ "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
+ "perfetto_protos_perfetto_config_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_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",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ "-DHAVE_HIDDEN",
+ ],
+ include_dirs: [
+ "bionic/libc/kernel",
+ ],
+ header_libs: [
+ "bionic_libc_platform_headers",
+ ],
+ data: [
+ "src/profiling/memory/test/data/**/*",
+ "src/traced/probes/filesystem/testdata/**/*",
+ "src/traced/probes/ftrace/test/data/**/*",
+ ],
}
// GN: //src/protozero/protoc_plugin:protozero_plugin
cc_binary_host {
- name: "protozero_plugin",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_src_base_base",
- "src/protozero/protoc_plugin/protozero_plugin.cc",
- ],
- static_libs: [
- "libprotoc",
- ],
- generated_headers: [
- "perfetto_src_base_version_gen_h",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- ],
+ name: "protozero_plugin",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_src_base_base",
+ "src/protozero/protoc_plugin/protozero_plugin.cc",
+ ],
+ static_libs: [
+ "libprotoc",
+ ],
+ generated_headers: [
+ "perfetto_src_base_version_gen_h",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ ],
}
// GN: //src/trace_processor:trace_processor_shell
cc_binary {
- 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",
- ":perfetto_include_perfetto_trace_processor_storage",
- ":perfetto_include_perfetto_trace_processor_trace_processor",
- ":perfetto_protos_perfetto_common_zero_gen",
- ":perfetto_protos_perfetto_config_android_zero_gen",
- ":perfetto_protos_perfetto_config_ftrace_zero_gen",
- ":perfetto_protos_perfetto_config_gpu_zero_gen",
- ":perfetto_protos_perfetto_config_inode_file_zero_gen",
- ":perfetto_protos_perfetto_config_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_trace_android_zero_gen",
- ":perfetto_protos_perfetto_trace_chrome_zero_gen",
- ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
- ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
- ":perfetto_protos_perfetto_trace_gpu_zero_gen",
- ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
- ":perfetto_protos_perfetto_trace_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
- ":perfetto_protos_perfetto_trace_power_zero_gen",
- ":perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
- ":perfetto_protos_perfetto_trace_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_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_gzip",
- ":perfetto_src_trace_processor_util_interned_message_view",
- ":perfetto_src_trace_processor_util_proto_to_args_parser",
- ":perfetto_src_trace_processor_util_protozero_to_text",
- ":perfetto_src_trace_processor_util_trace_blob_view",
- ":perfetto_src_trace_processor_util_util",
- "src/trace_processor/trace_processor_shell.cc",
- "src/trace_processor/util/proto_to_json.cc",
- ],
- host_supported: true,
- generated_headers: [
- "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_trace_android_zero_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
- "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
- "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
- "perfetto_protos_perfetto_trace_power_zero_gen_headers",
- "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
- "perfetto_protos_perfetto_trace_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",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_HIDDEN",
- ],
- strip: {
- all: true,
- },
- target: {
- android: {
- shared_libs: [
- "libandroidicu",
- "liblog",
- "libprotobuf-cpp-full",
- "libsqlite",
- "libutils",
- "libz",
- ],
+ 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",
+ ":perfetto_include_perfetto_trace_processor_storage",
+ ":perfetto_include_perfetto_trace_processor_trace_processor",
+ ":perfetto_protos_perfetto_common_zero_gen",
+ ":perfetto_protos_perfetto_config_android_zero_gen",
+ ":perfetto_protos_perfetto_config_ftrace_zero_gen",
+ ":perfetto_protos_perfetto_config_gpu_zero_gen",
+ ":perfetto_protos_perfetto_config_inode_file_zero_gen",
+ ":perfetto_protos_perfetto_config_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_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_chrome_zero_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
+ ":perfetto_protos_perfetto_trace_gpu_zero_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+ ":perfetto_protos_perfetto_trace_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
+ ":perfetto_protos_perfetto_trace_power_zero_gen",
+ ":perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
+ ":perfetto_protos_perfetto_trace_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_base_unix_socket",
+ ":perfetto_src_profiling_deobfuscator",
+ ":perfetto_src_profiling_symbolizer_symbolize_database",
+ ":perfetto_src_profiling_symbolizer_symbolizer",
+ ":perfetto_src_protozero_proto_ring_buffer",
+ ":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_rpc_httpd",
+ ":perfetto_src_trace_processor_rpc_rpc",
+ ":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_gzip",
+ ":perfetto_src_trace_processor_util_interned_message_view",
+ ":perfetto_src_trace_processor_util_proto_to_args_parser",
+ ":perfetto_src_trace_processor_util_protozero_to_text",
+ ":perfetto_src_trace_processor_util_trace_blob_view",
+ ":perfetto_src_trace_processor_util_util",
+ "src/trace_processor/trace_processor_shell.cc",
+ "src/trace_processor/util/proto_to_json.cc",
+ ],
+ host_supported: true,
+ generated_headers: [
+ "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_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_power_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_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",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ "-DHAVE_HIDDEN",
+ ],
+ strip: {
+ all: true,
},
- host: {
- static_libs: [
- "libprotobuf-cpp-full",
- "libsqlite",
- "libz",
- ],
- stl: "libc++_static",
- dist: {
- targets: [
- "sdk_repo",
- ],
- },
+ 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",
+ ],
+ },
+ },
},
- },
}
// GN: //tools/trace_to_text:trace_to_text
cc_binary_host {
- name: "trace_to_text",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_ext_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_pprof_builder",
- ":perfetto_include_perfetto_protozero_protozero",
- ":perfetto_include_perfetto_trace_processor_basic_types",
- ":perfetto_include_perfetto_trace_processor_storage",
- ":perfetto_include_perfetto_trace_processor_trace_processor",
- ":perfetto_protos_perfetto_common_zero_gen",
- ":perfetto_protos_perfetto_config_android_zero_gen",
- ":perfetto_protos_perfetto_config_ftrace_zero_gen",
- ":perfetto_protos_perfetto_config_gpu_zero_gen",
- ":perfetto_protos_perfetto_config_inode_file_zero_gen",
- ":perfetto_protos_perfetto_config_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_trace_android_zero_gen",
- ":perfetto_protos_perfetto_trace_chrome_zero_gen",
- ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
- ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
- ":perfetto_protos_perfetto_trace_gpu_zero_gen",
- ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
- ":perfetto_protos_perfetto_trace_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
- ":perfetto_protos_perfetto_trace_power_zero_gen",
- ":perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
- ":perfetto_protos_perfetto_trace_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_protos_third_party_pprof_zero_gen",
- ":perfetto_src_base_base",
- ":perfetto_src_profiling_deobfuscator",
- ":perfetto_src_profiling_symbolizer_symbolize_database",
- ":perfetto_src_profiling_symbolizer_symbolizer",
- ":perfetto_src_protozero_proto_ring_buffer",
- ":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_gzip",
- ":perfetto_src_trace_processor_util_interned_message_view",
- ":perfetto_src_trace_processor_util_proto_to_args_parser",
- ":perfetto_src_trace_processor_util_protozero_to_text",
- ":perfetto_src_trace_processor_util_trace_blob_view",
- ":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: [
- "libprotobuf-cpp-full",
- "libsqlite",
- "libz",
- ],
- generated_headers: [
- "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_trace_android_zero_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
- "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
- "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
- "perfetto_protos_perfetto_trace_power_zero_gen_headers",
- "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
- "perfetto_protos_perfetto_trace_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",
- "perfetto_tools_trace_to_text_gen_cc_trace_descriptor",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_HIDDEN",
- ],
+ name: "trace_to_text",
+ 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_profiling_pprof_builder",
+ ":perfetto_include_perfetto_protozero_protozero",
+ ":perfetto_include_perfetto_trace_processor_basic_types",
+ ":perfetto_include_perfetto_trace_processor_storage",
+ ":perfetto_include_perfetto_trace_processor_trace_processor",
+ ":perfetto_protos_perfetto_common_zero_gen",
+ ":perfetto_protos_perfetto_config_android_zero_gen",
+ ":perfetto_protos_perfetto_config_ftrace_zero_gen",
+ ":perfetto_protos_perfetto_config_gpu_zero_gen",
+ ":perfetto_protos_perfetto_config_inode_file_zero_gen",
+ ":perfetto_protos_perfetto_config_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_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_chrome_zero_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
+ ":perfetto_protos_perfetto_trace_gpu_zero_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+ ":perfetto_protos_perfetto_trace_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
+ ":perfetto_protos_perfetto_trace_power_zero_gen",
+ ":perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
+ ":perfetto_protos_perfetto_trace_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_protos_third_party_pprof_zero_gen",
+ ":perfetto_src_base_base",
+ ":perfetto_src_profiling_deobfuscator",
+ ":perfetto_src_profiling_symbolizer_symbolize_database",
+ ":perfetto_src_profiling_symbolizer_symbolizer",
+ ":perfetto_src_protozero_proto_ring_buffer",
+ ":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_gzip",
+ ":perfetto_src_trace_processor_util_interned_message_view",
+ ":perfetto_src_trace_processor_util_proto_to_args_parser",
+ ":perfetto_src_trace_processor_util_protozero_to_text",
+ ":perfetto_src_trace_processor_util_trace_blob_view",
+ ":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: [
+ "libprotobuf-cpp-full",
+ "libsqlite",
+ "libz",
+ ],
+ generated_headers: [
+ "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_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_power_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_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",
+ "perfetto_tools_trace_to_text_gen_cc_trace_descriptor",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ "-DHAVE_HIDDEN",
+ ],
}
// GN: //src/traced/service:traced
cc_binary {
- name: "traced",
- srcs: [
- ":perfetto_include_perfetto_ext_traced_traced",
- "src/traced/service/main.cc",
- ],
- shared_libs: [
- "liblog",
- "libperfetto",
- ],
- init_rc: [
- "perfetto.rc",
- ],
- defaults: [
- "perfetto_defaults",
- ],
+ name: "traced",
+ srcs: [
+ ":perfetto_include_perfetto_ext_traced_traced",
+ "src/traced/service/main.cc",
+ ],
+ shared_libs: [
+ "liblog",
+ "libperfetto",
+ ],
+ init_rc: [
+ "perfetto.rc",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
}
// GN: //src/profiling/perf:traced_perf
cc_binary {
- name: "traced_perf",
- 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_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",
- ":perfetto_src_profiling_perf_producer",
- ":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",
- ":perfetto_src_tracing_ipc_common",
- ":perfetto_src_tracing_ipc_producer_producer",
- "src/profiling/perf/main.cc",
- ],
- shared_libs: [
- "libbase",
- "liblog",
- "libprocinfo",
- "libunwindstack",
- ],
- init_rc: [
- "traced_perf.rc",
- ],
- 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",
- ],
- include_dirs: [
- "bionic/libc/kernel",
- ],
+ name: "traced_perf",
+ 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_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",
+ ":perfetto_src_profiling_perf_producer",
+ ":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",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ "src/profiling/perf/main.cc",
+ ],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libprocinfo",
+ "libunwindstack",
+ ],
+ init_rc: [
+ "traced_perf.rc",
+ ],
+ 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",
+ ],
+ include_dirs: [
+ "bionic/libc/kernel",
+ ],
}
// GN: //src/traced/probes:traced_probes
cc_binary {
- name: "traced_probes",
- srcs: [
- ":perfetto_include_perfetto_ext_traced_traced",
- "src/traced/probes/main.cc",
- ],
- shared_libs: [
- "liblog",
- "libperfetto",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- required: [
- "libperfetto_android_internal",
- "mm_events",
- "traced_perf",
- "trigger_perfetto",
- ],
+ name: "traced_probes",
+ srcs: [
+ ":perfetto_include_perfetto_ext_traced_traced",
+ "src/traced/probes/main.cc",
+ ],
+ shared_libs: [
+ "liblog",
+ "libperfetto",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ required: [
+ "libperfetto_android_internal",
+ "mm_events",
+ "traced_perf",
+ "trigger_perfetto",
+ ],
}
// GN: //src/perfetto_cmd:trigger_perfetto
cc_binary {
- name: "trigger_perfetto",
- srcs: [
- ":perfetto_include_perfetto_base_base",
- ":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_ext_ipc_ipc",
- ":perfetto_include_perfetto_ext_traced_traced",
- ":perfetto_include_perfetto_ext_tracing_core_core",
- ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
- ":perfetto_include_perfetto_protozero_protozero",
- ":perfetto_include_perfetto_tracing_core_core",
- ":perfetto_include_perfetto_tracing_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_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_protos_gen",
- ":perfetto_src_perfetto_cmd_trigger_perfetto_cmd",
- ":perfetto_src_perfetto_cmd_trigger_producer",
- ":perfetto_src_protozero_protozero",
- ":perfetto_src_tracing_common",
- ":perfetto_src_tracing_core_core",
- ":perfetto_src_tracing_ipc_common",
- ":perfetto_src_tracing_ipc_producer_producer",
- "src/perfetto_cmd/trigger_perfetto_main.cc",
- ],
- shared_libs: [
- "liblog",
- ],
- 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",
- "perfetto_src_perfetto_cmd_protos_gen_headers",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- ],
+ name: "trigger_perfetto",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_ipc_ipc",
+ ":perfetto_include_perfetto_ext_traced_traced",
+ ":perfetto_include_perfetto_ext_tracing_core_core",
+ ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+ ":perfetto_include_perfetto_protozero_protozero",
+ ":perfetto_include_perfetto_tracing_core_core",
+ ":perfetto_include_perfetto_tracing_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_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_protos_gen",
+ ":perfetto_src_perfetto_cmd_trigger_perfetto_cmd",
+ ":perfetto_src_perfetto_cmd_trigger_producer",
+ ":perfetto_src_protozero_protozero",
+ ":perfetto_src_tracing_common",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ "src/perfetto_cmd/trigger_perfetto_main.cc",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ 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",
+ "perfetto_src_perfetto_cmd_protos_gen_headers",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ ],
}
// These targets are appended to the autogenerated Android.bp by tools/gen_android_bp.
java_library_host {
- name: "perfetto_config-full",
- proto: {
- type: "full",
- },
- srcs: [
- "protos/perfetto/config/perfetto_config.proto",
- ],
+ name: "perfetto_config-full",
+ proto: {
+ type: "full",
+ },
+ srcs: [
+ "protos/perfetto/config/perfetto_config.proto",
+ ],
}
java_library_host {
- name: "perfetto_metrics-full",
- proto: {
- type: "full",
- },
- srcs: [
- "protos/perfetto/metrics/perfetto_merged_metrics.proto",
- ],
+ name: "perfetto_metrics-full",
+ proto: {
+ type: "full",
+ },
+ srcs: [
+ "protos/perfetto/metrics/perfetto_merged_metrics.proto",
+ ],
}
// This sample target shows how to use the perfetto client API from within the
// Android tree.
cc_binary {
- name: "libperfetto_client_example",
- srcs: [
- "test/client_api_example.cc",
- ],
- static_libs: [
- "libperfetto_client_experimental",
- "perfetto_trace_protos",
- ],
- shared_libs: [
- "libprotobuf-cpp-lite",
- "liblog",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- ],
- defaults: [
- "perfetto_defaults",
- ],
+ name: "libperfetto_client_example",
+ srcs: [
+ "test/client_api_example.cc",
+ ],
+ static_libs: [
+ "libperfetto_client_experimental",
+ "perfetto_trace_protos",
+ ],
+ shared_libs: [
+ "libprotobuf-cpp-lite",
+ "liblog",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
}
cc_library_static {
diff --git a/Android.bp.extras b/Android.bp.extras
index 53140dd..c447a86 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -1,47 +1,47 @@
// These targets are appended to the autogenerated Android.bp by tools/gen_android_bp.
java_library_host {
- name: "perfetto_config-full",
- proto: {
- type: "full",
- },
- srcs: [
- "protos/perfetto/config/perfetto_config.proto",
- ],
+ name: "perfetto_config-full",
+ proto: {
+ type: "full",
+ },
+ srcs: [
+ "protos/perfetto/config/perfetto_config.proto",
+ ],
}
java_library_host {
- name: "perfetto_metrics-full",
- proto: {
- type: "full",
- },
- srcs: [
- "protos/perfetto/metrics/perfetto_merged_metrics.proto",
- ],
+ name: "perfetto_metrics-full",
+ proto: {
+ type: "full",
+ },
+ srcs: [
+ "protos/perfetto/metrics/perfetto_merged_metrics.proto",
+ ],
}
// This sample target shows how to use the perfetto client API from within the
// Android tree.
cc_binary {
- name: "libperfetto_client_example",
- srcs: [
- "test/client_api_example.cc",
- ],
- static_libs: [
- "libperfetto_client_experimental",
- "perfetto_trace_protos",
- ],
- shared_libs: [
- "libprotobuf-cpp-lite",
- "liblog",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- ],
- defaults: [
- "perfetto_defaults",
- ],
+ name: "libperfetto_client_example",
+ srcs: [
+ "test/client_api_example.cc",
+ ],
+ static_libs: [
+ "libperfetto_client_experimental",
+ "perfetto_trace_protos",
+ ],
+ shared_libs: [
+ "libprotobuf-cpp-lite",
+ "liblog",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
}
cc_library_static {
diff --git a/BUILD b/BUILD
index db42ce5..264030b 100644
--- a/BUILD
+++ b/BUILD
@@ -169,6 +169,42 @@
],
)
+# GN target: //tools/proto_filter:proto_filter
+perfetto_cc_binary(
+ name = "proto_filter",
+ srcs = [
+ ":src_protozero_filtering_bytecode_common",
+ ":src_protozero_filtering_bytecode_generator",
+ ":src_protozero_filtering_bytecode_parser",
+ ":src_protozero_filtering_filter_util",
+ ":src_protozero_filtering_message_filter",
+ "tools/proto_filter/proto_filter.cc",
+ ],
+ deps = [
+ ":protozero",
+ ":src_base_base",
+ ] + PERFETTO_CONFIG.deps.protobuf_full,
+)
+
+# GN target: //tools/proto_merger:proto_merger
+perfetto_cc_binary(
+ name = "proto_merger",
+ srcs = [
+ "tools/proto_merger/allowlist.cc",
+ "tools/proto_merger/allowlist.h",
+ "tools/proto_merger/main.cc",
+ "tools/proto_merger/proto_file.cc",
+ "tools/proto_merger/proto_file.h",
+ "tools/proto_merger/proto_file_serializer.cc",
+ "tools/proto_merger/proto_file_serializer.h",
+ "tools/proto_merger/proto_merger.cc",
+ "tools/proto_merger/proto_merger.h",
+ ],
+ deps = [
+ ":src_base_base",
+ ] + PERFETTO_CONFIG.deps.protobuf_full,
+)
+
# GN target: //:libperfetto
perfetto_cc_library(
name = "libperfetto",
@@ -751,9 +787,11 @@
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/breakpad_parser.cc",
+ "src/profiling/symbolizer/breakpad_parser.h",
+ "src/profiling/symbolizer/breakpad_symbolizer.cc",
+ "src/profiling/symbolizer/breakpad_symbolizer.h",
+ "src/profiling/symbolizer/elf.h",
"src/profiling/symbolizer/local_symbolizer.cc",
"src/profiling/symbolizer/local_symbolizer.h",
"src/profiling/symbolizer/scoped_read_mmap.h",
@@ -784,6 +822,15 @@
],
)
+# GN target: //src/protozero/filtering:bytecode_generator
+filegroup(
+ name = "src_protozero_filtering_bytecode_generator",
+ srcs = [
+ "src/protozero/filtering/filter_bytecode_generator.cc",
+ "src/protozero/filtering/filter_bytecode_generator.h",
+ ],
+)
+
# GN target: //src/protozero/filtering:bytecode_parser
filegroup(
name = "src_protozero_filtering_bytecode_parser",
@@ -793,6 +840,15 @@
],
)
+# GN target: //src/protozero/filtering:filter_util
+filegroup(
+ name = "src_protozero_filtering_filter_util",
+ srcs = [
+ "src/protozero/filtering/filter_util.cc",
+ "src/protozero/filtering/filter_util.h",
+ ],
+)
+
# GN target: //src/protozero/filtering:message_filter
filegroup(
name = "src_protozero_filtering_message_filter",
@@ -969,6 +1025,8 @@
"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_multiuser.sql",
+ "src/trace_processor/metrics/android/android_multiuser_populator.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",
@@ -976,8 +1034,10 @@
"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_sysui_cuj_jank_query.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/android_trace_quality.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",
@@ -986,6 +1046,7 @@
"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/gpu_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",
@@ -997,7 +1058,9 @@
"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/profiler_smaps.sql",
"src/trace_processor/metrics/android/span_view_stats.sql",
+ "src/trace_processor/metrics/android/thread_counter_span_view.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",
@@ -1008,6 +1071,9 @@
"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/gesture_flow_event.sql",
+ "src/trace_processor/metrics/chrome/gesture_flow_event_queuing_delay.sql",
+ "src/trace_processor/metrics/chrome/gesture_jank.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",
@@ -1018,6 +1084,9 @@
"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/chrome/touch_flow_event.sql",
+ "src/trace_processor/metrics/chrome/touch_flow_event_queuing_delay.sql",
+ "src/trace_processor/metrics/chrome/touch_jank.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",
@@ -1227,8 +1296,8 @@
"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/descendant_generator.cc",
+ "src/trace_processor/dynamic/descendant_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",
@@ -1237,6 +1306,8 @@
"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_flat_slice_generator.cc",
+ "src/trace_processor/dynamic/experimental_flat_slice_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",
@@ -1358,6 +1429,8 @@
"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/flamegraph_construction_algorithms.cc",
+ "src/trace_processor/importers/proto/flamegraph_construction_algorithms.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",
@@ -2487,14 +2560,17 @@
"protos/perfetto/metrics/android/lmk_reason_metric.proto",
"protos/perfetto/metrics/android/mem_metric.proto",
"protos/perfetto/metrics/android/mem_unagg_metric.proto",
+ "protos/perfetto/metrics/android/multiuser_metric.proto",
"protos/perfetto/metrics/android/package_list.proto",
"protos/perfetto/metrics/android/powrails_metric.proto",
"protos/perfetto/metrics/android/process_metadata.proto",
+ "protos/perfetto/metrics/android/profiler_smaps.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/trace_quality.proto",
"protos/perfetto/metrics/android/unsymbolized_frames.proto",
],
visibility = PERFETTO_CONFIG.public_visibility,
@@ -2522,6 +2598,7 @@
"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/chrome/touch_jank.proto",
],
visibility = [
PERFETTO_CONFIG.proto_library_visibility,
@@ -3352,6 +3429,26 @@
],
)
+# GN target: //protos/third_party/chromium:lite
+perfetto_cc_proto_library(
+ name = "protos_third_party_chromium_lite",
+ deps = [
+ ":protos_third_party_chromium_protos",
+ ],
+)
+
+# GN target: //protos/third_party/chromium:lite
+perfetto_proto_library(
+ name = "protos_third_party_chromium_protos",
+ srcs = [
+ "protos/third_party/chromium/chrome_track_event.proto",
+ ],
+ visibility = PERFETTO_CONFIG.public_visibility,
+ deps = [
+ ":protos_perfetto_trace_track_event_protos",
+ ],
+)
+
# GN target: //protos/third_party/pprof:zero
perfetto_proto_library(
name = "protos_third_party_pprof_protos",
@@ -4024,38 +4121,10 @@
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"],
+ deps = [":trace_processor_py"] + PERFETTO_CONFIG.deps.pandas_py,
main = "src/trace_processor/python/example.py",
python_version = "PY3",
)
@@ -4064,16 +4133,39 @@
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",
+ ] + PERFETTO_CONFIG.deps.tp_init_py,
+ deps = PERFETTO_CONFIG.deps.gfile_py +
+ PERFETTO_CONFIG.deps.protobuf_py +
+ PERFETTO_CONFIG.deps.protobuf_descriptor_pb2_py +
+ PERFETTO_CONFIG.deps.pyglib_py,
+ imports = [
+ "src/trace_processor/python",
],
visibility = PERFETTO_CONFIG.public_visibility,
)
+
+perfetto_py_library(
+ name = "experimental_slice_breakdown_lib",
+ srcs = glob(["tools/slice_breakdown/perfetto/slice_breakdown/*.py"]),
+ deps = [
+ ":trace_processor_py",
+ ],
+ imports = [
+ "tools/slice_breakdown",
+ ],
+)
+
+perfetto_py_binary(
+ name = "experimental_slice_breakdown_bin",
+ srcs = ["tools/slice_breakdown/main.py"],
+ main = "tools/slice_breakdown/main.py",
+ deps = [
+ ":experimental_slice_breakdown_lib",
+ ":trace_processor_py",
+ ] + PERFETTO_CONFIG.deps.pandas_py,
+ python_version = "PY3",
+ legacy_create_init = 0,
+)
diff --git a/BUILD.extras b/BUILD.extras
index 53392a7..be5aa90 100644
--- a/BUILD.extras
+++ b/BUILD.extras
@@ -93,38 +93,10 @@
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"],
+ deps = [":trace_processor_py"] + PERFETTO_CONFIG.deps.pandas_py,
main = "src/trace_processor/python/example.py",
python_version = "PY3",
)
@@ -133,16 +105,39 @@
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",
+ ] + PERFETTO_CONFIG.deps.tp_init_py,
+ deps = PERFETTO_CONFIG.deps.gfile_py +
+ PERFETTO_CONFIG.deps.protobuf_py +
+ PERFETTO_CONFIG.deps.protobuf_descriptor_pb2_py +
+ PERFETTO_CONFIG.deps.pyglib_py,
+ imports = [
+ "src/trace_processor/python",
],
visibility = PERFETTO_CONFIG.public_visibility,
)
+
+perfetto_py_library(
+ name = "experimental_slice_breakdown_lib",
+ srcs = glob(["tools/slice_breakdown/perfetto/slice_breakdown/*.py"]),
+ deps = [
+ ":trace_processor_py",
+ ],
+ imports = [
+ "tools/slice_breakdown",
+ ],
+)
+
+perfetto_py_binary(
+ name = "experimental_slice_breakdown_bin",
+ srcs = ["tools/slice_breakdown/main.py"],
+ main = "tools/slice_breakdown/main.py",
+ deps = [
+ ":experimental_slice_breakdown_lib",
+ ":trace_processor_py",
+ ] + PERFETTO_CONFIG.deps.pandas_py,
+ python_version = "PY3",
+ legacy_create_init = 0,
+)
diff --git a/CHANGELOG b/CHANGELOG
index c01f292..e63367e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,14 +1,100 @@
Unreleased:
Tracing service and probes:
- *
+ * Removed DCHECK that would cause crashes when a debug build of the service
+ is used with a producer built with -DNDEBUG.
+ * Changed the service-side field-level filtering configuration protobuf
+ field number, because the feature had a bug. This is effectively
+ equivalent to deprecating the feature and reintroducing it under a
+ different name.
Trace Processor:
+ * Added reqiurement of separating queries by semi-colon (;) followed by
+ new-line when specifying a query file with -q to trace processor shell.
+ * Added "ancestor_slice_by_stack" and "descendant_slice_by_stack" table
+ functions to walk up and down the slice stacks.
+ * Overhauled windowed sorting to be based on packet ordering and
+ lifecycle events inside the trace instead of time-based ordering.
+ * Deprecated |SortingMode::kForceFlushPeriodWindowedSort| due to
+ windowed sorting chagnes. Embedders should switch to
+ |SortingMode::kDefaultHeuristics|; this option will be removed
+ in v21.
+ UI:
*
+ SDK:
+ * Changed DCHECK and DLOGs to be always disabled in SDK builds, regardless
+ of NDEBUG.
+
+
+v19.0 - 2021-09-02:
+ Tracing service and probes:
+ * Added ftrace clock reporting to the trace.
+ Trace Processor:
+ * Added support for longs/doubles to RUN_METRIC.
+ * Added power profile data for sunfish, redfin, and bramble.
+ * Added experimental Python library for computing slice breakdowns.
+ * Fixed parsing of JSON escape sequences.
+ * Fixed JSON trace detection.
+ UI:
+ * Added local cacheing of traces. Traces are reloaded in case of refresh or
+ tab being discarded by the browser.
+ * Added icon to distinguish metric-derived tracks.
+ * Added release channel selector to feature flags page.
+ * Fixed crash with null slice names.
+ SDK:
+ * Added some missing NESTABLE_ASYNC legacy trace macros.
+ * Fixed reporting of producer uid in --query.
+ * Fixed version numbering scheme for minor versions. Previously versions
+ were numbered as like v19.0.42 where 42 represented the number of commits
+ since the last major version release. This was ambiguous in the presence
+ of branches. Now versions are numbered like v19.0-ab12cd34 where ab12cd34
+ is the shortened Git commit-ish.
+
+
+v18.0 - 2021-08-02:
+ Tracing service and probes:
+ * Added cross-compiler toolchains for Linux-{arm,64} based on Debian Sid.
+ These will be used for generating monthly releases' prebuilts via LUCI.
+ Trace Processor:
+ * Added 'android_gpu' metric to report residency information for each GPU
+ frequency (via `trace_processor_shell --run-metrics android_gpu`).
+ * Removed the RawQuery RPC interface.
+ UI:
+ * Added a highlighted section to thread slices to visualize CPU time
+ (darker) verses wall time (lighter).
+ * Added global counter tracks for perf counters (e.g. "CPU 0 cycles", "CPU 0
+ instructions") when the 'linux.perf' data source (traced_perf) is used.
+ * Added a (feature) 'Flags' page to enable/disable individual metrics.
+ * Fixed races that could cause occasional crashes when loading a trace
+ from a permalink.
+ SDK:
+ * Fix undefined reference on ~TracingMuxerFake when building the SDK.
+
+
+v17.0 - 2021-07-02:
+ Tracing service and probes:
+ * Fixed a bug in ftrace parsing of absolute timestamps
+ (RINGBUF_TYPE_TIME_STAMP), encountered on Linux kernels 5.9+.
+ * Fixed a bug in --save-for-bugreport causing 0-length traces if the
+ selected trace declared one or more triggers in the config.
+ * Fixed a bug in tracebox causing the PERFETTO_PRODUCER_SOCK_NAME env
+ var to be ignored.
+ Trace Processor:
+ * Changed CORS headers of --httpd mode to allow only https://ui.perfetto.dev
+ and http://localhost:10000. This affects only CORS-aware browser clients.
+ * Added GPU frequency metrics.
UI:
* Fixed ADB connection issues ("unable to reset device") on Windows and Mac.
+ * Added caching of tracing in the cache storage so that the trace is
+ re-opened if a tab is killed (Chrome tab discarding or accidental CTRL+W).
SDK:
* Added support for writing track events using custom clock timestamps.
+v16.1 - 2021-06-08:
+ Tracing service and probes:
+ * Cherry-pick of r.android.com/1716718 which missed the v16 branch cut and
+ fixed MSVC 2019 builds.
+
+
v16.0 - 2021-06-01:
Tracing service and probes:
* Added support for building most targets (including traced, SDK and
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 97acb3e..9f5fa6f 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -12,8 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import print_function
import itertools
import subprocess
+import time
+
+
+def RunAndReportIfLong(func, *args, **kargs):
+ start = time.time()
+ results = func(*args, **kargs)
+ end = time.time()
+ limit = 0.5 # seconds
+ name = func.__name__
+ runtime = end - start
+ if runtime > limit:
+ print("{} took >{:.2}s ({:.2}s)".format(name, limit, runtime))
+ return results
def CheckChange(input, output):
@@ -24,29 +38,43 @@
x,
files_to_check='.*',
files_to_skip=[
- 'Android[.]bp', '.*[.]json$', '.*[.]sql$', '.*[.]out$',
- 'test/trace_processor/.*/index$', '(.*/)?BUILD$', 'WORKSPACE',
- '.*/Makefile$', '/perfetto_build_flags.h$'
+ 'Android[.]bp',
+ '.*[.]json$',
+ '.*[.]sql$',
+ '.*[.]out$',
+ 'test/trace_processor/.*/index$',
+ '(.*/)?BUILD$',
+ 'WORKSPACE',
+ '.*/Makefile$',
+ '/perfetto_build_flags.h$',
+ "infra/luci/.*",
])
results = []
- results += input.canned_checks.CheckDoNotSubmit(input, output)
- results += input.canned_checks.CheckChangeHasNoTabs(input, output)
- results += input.canned_checks.CheckLongLines(
- input, output, 80, source_file_filter=long_line_sources)
- results += input.canned_checks.CheckPatchFormatted(
- input, output, check_js=True)
- results += input.canned_checks.CheckGNFormatted(input, output)
- results += CheckIncludeGuards(input, output)
- results += CheckIncludeViolations(input, output)
- results += CheckProtoComments(input, output)
- results += CheckBuild(input, output)
- results += CheckAndroidBlueprint(input, output)
- results += CheckBinaryDescriptors(input, output)
- results += CheckMergedTraceConfigProto(input, output)
- results += CheckProtoEventList(input, output)
- results += CheckBannedCpp(input, output)
- results += CheckSqlMetrics(input, output)
+ results += RunAndReportIfLong(input.canned_checks.CheckDoNotSubmit, input,
+ output)
+ results += RunAndReportIfLong(input.canned_checks.CheckChangeHasNoTabs, input,
+ output)
+ results += RunAndReportIfLong(
+ input.canned_checks.CheckLongLines,
+ input,
+ output,
+ 80,
+ source_file_filter=long_line_sources)
+ results += RunAndReportIfLong(
+ input.canned_checks.CheckPatchFormatted, input, output, check_js=True)
+ results += RunAndReportIfLong(input.canned_checks.CheckGNFormatted, input,
+ output)
+ results += RunAndReportIfLong(CheckIncludeGuards, input, output)
+ results += RunAndReportIfLong(CheckIncludeViolations, input, output)
+ results += RunAndReportIfLong(CheckProtoComments, input, output)
+ results += RunAndReportIfLong(CheckBuild, input, output)
+ results += RunAndReportIfLong(CheckAndroidBlueprint, input, output)
+ results += RunAndReportIfLong(CheckBinaryDescriptors, input, output)
+ results += RunAndReportIfLong(CheckMergedTraceConfigProto, input, output)
+ results += RunAndReportIfLong(CheckProtoEventList, input, output)
+ results += RunAndReportIfLong(CheckBannedCpp, input, output)
+ results += RunAndReportIfLong(CheckSqlMetrics, input, output)
return results
@@ -132,6 +160,8 @@
(r'\bPERFETTO_EINTR\(close\(',
'close(2) must not be retried on EINTR on Linux and other OSes '
'that we run on, as the fd will be closed.'),
+ (r'^#include <inttypes.h>', 'Use <cinttypes> rather than <inttypes.h>. ' +
+ 'See https://github.com/google/perfetto/issues/146'),
]
def file_filter(x):
diff --git a/bazel/BUILD b/bazel/BUILD
index 1bf33a4..bf64b69 100644
--- a/bazel/BUILD
+++ b/bazel/BUILD
@@ -14,19 +14,25 @@
config_setting(
name = "os_osx",
- values = {"cpu": "darwin"},
+ constraint_values = [
+ "@platforms//os:macos",
+ ],
visibility = ["//visibility:public"],
)
config_setting(
name = "os_linux",
- values = {"cpu": "k8"},
+ constraint_values = [
+ "@platforms//os:linux",
+ ],
visibility = ["//visibility:public"],
)
# Note this config does not imply MSVC.
config_setting(
name = "os_windows",
- values = {"cpu": "x64_windows"},
+ constraint_values = [
+ "@platforms//os:windows",
+ ],
visibility = ["//visibility:public"],
)
diff --git a/bazel/deps.bzl b/bazel/deps.bzl
index 63cbde2..c5ad01c 100644
--- a/bazel/deps.bzl
+++ b/bazel/deps.bzl
@@ -25,7 +25,7 @@
http_archive,
name = "com_google_protobuf",
strip_prefix = "protobuf-3.9.0",
- url = "https://github.com/google/protobuf/archive/v3.9.0.tar.gz",
+ url = "https://github.com/protocolbuffers/protobuf/archive/v3.9.0.tar.gz",
sha256 = "2ee9dcec820352671eb83e081295ba43f7a4157181dad549024d7070d079cf65",
)
diff --git a/bazel/standalone/perfetto_cfg.bzl b/bazel/standalone/perfetto_cfg.bzl
index 2d71aa8..5725041 100644
--- a/bazel/standalone/perfetto_cfg.bzl
+++ b/bazel/standalone/perfetto_cfg.bzl
@@ -49,7 +49,16 @@
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"]
+ protobuf_descriptor_proto = ["@com_google_protobuf//:descriptor_proto"],
+
+ # The Python targets are empty on the standalone build because we assume
+ # any relevant deps are installed on the system or are not applicable.
+ tp_init_py = [],
+ gfile_py = [],
+ protobuf_py = [],
+ protobuf_descriptor_pb2_py = [],
+ pyglib_py = [],
+ pandas_py = [],
),
# This struct allows embedders to customize the cc_opts for Perfetto
diff --git a/buildtools/.gitignore b/buildtools/.gitignore
index 0888b62..e29be60 100644
--- a/buildtools/.gitignore
+++ b/buildtools/.gitignore
@@ -1,16 +1,20 @@
+android_sdk/
android-core/
android-libbase/
android-libprocinfo/
android-logging/
android-unwinding/
-android_sdk/
aosp-*/
benchmark/
bionic/
+bloaty/
catapult_trace_viewer/
-clang/
clang_format/
+clang/
d8/
+debian_sid_arm-sysroot/
+debian_sid_arm64-sysroot/
+debian_sid_armel-sysroot/
emulator/
googletest/
jsoncpp/
@@ -28,8 +32,8 @@
ndk/
nodejs/
protobuf/
-sqlite/
sqlite_src/
+sqlite/
test_data/
typefaces/
win/
diff --git a/codereview.settings b/codereview.settings
index f6b44a5..06bf287 100644
--- a/codereview.settings
+++ b/codereview.settings
@@ -2,3 +2,4 @@
GERRIT_HOST: True
CODE_REVIEW_SERVER: https://android-review.googlesource.com
PROJECT: platform/external/perfetto
+USE_PYTHON3: True
diff --git a/debian/postinst b/debian/postinst
index e6cdff5..a583930 100755
--- a/debian/postinst
+++ b/debian/postinst
@@ -3,5 +3,7 @@
adduser --home /nonexistent --quiet --system --no-create-home --group traced
addgroup --quiet --system traced-consumer
usermod -a -G traced-consumer traced
+mkdir -m 755 /run/perfetto
+chown traced:traced /run/perfetto
#DEBHELPER#
diff --git a/debian/postrm b/debian/postrm
index efa1590..8f8abc0 100755
--- a/debian/postrm
+++ b/debian/postrm
@@ -1,5 +1,5 @@
#!/bin/sh
set -e
-rm -f /tmp/perfetto-consumer /tmp/perfetto-producer
+rm -rf /run/perfetto
#DEBHELPER#
diff --git a/docs/analysis/trace-processor.md b/docs/analysis/trace-processor.md
index d9059c7..a7df0c8 100644
--- a/docs/analysis/trace-processor.md
+++ b/docs/analysis/trace-processor.md
@@ -49,7 +49,7 @@
* [trace_processor](/docs/analysis/trace-processor.md), a standalone binary
providing a shell interface (and the reference embedder).
* [Perfetto UI](https://ui.perfetto.dev), in the form of a WebAssembly module.
-* [Android Graphics Inspector](https://gpuinspector.dev/).
+* [Android GPU Inspector](https://gpuinspector.dev/).
* [Android Studio](https://developer.android.com/studio/).
## Concepts
@@ -299,26 +299,27 @@
-- Get all the scheduling slices
CREATE VIEW sp_sched AS
SELECT ts, dur, cpu, utid
-FROM sched
+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,
+ lead(ts) OVER (PARTITION BY track_id ORDER BY ts) - ts as dur,
cpu,
value as freq
FROM counter
+JOIN cpu_counter_track ON counter.track_id = cpu_counter_track.id;
-- 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)
+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
+FROM sched_with_frequency;
```
NOTE: A partition can be specified on neither, either or both tables. If
@@ -354,6 +355,32 @@
ancestor_slice(interesting_slices.id) AS ancestor ON ancestor.depth = 0
```
+### Ancestor slice by stack
+ancestor_slice_by_stack is a custom operator table that takes a
+[slice table's stack_id column](/docs/analysis/sql-tables.autogen#slice) and
+finds all slice ids with that stack_id, then, for each id it computes
+all the ancestor slices similarly to
+[ancestor_slice](/docs/analysis/trace-processor#ancestor-slice).
+
+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 of all slices with the
+given name.
+
+```sql
+CREATE VIEW interesting_stack_ids AS
+SELECT stack_id
+FROM slice WHERE name LIKE "%interesting slice name%";
+
+SELECT
+ *
+FROM
+ interesting_stack_ids LEFT JOIN
+ ancestor_slice_by_stack(interesting_stack_ids.stack_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
@@ -382,6 +409,32 @@
FROM interesting_slices
```
+### Descendant slice by stack
+descendant_slice_by_stack is a custom operator table that takes a
+[slice table's stack_id column](/docs/analysis/sql-tables.autogen#slice) and
+finds all slice ids with that stack_id, then, for each id it computes
+all the descendant slices similarly to
+[descendant_slice](/docs/analysis/trace-processor#descendant-slice).
+
+The returned format is the same as the
+[slice table](/docs/analysis/sql-tables.autogen#slice)
+
+For example, the following finds the next level descendant of all slices with
+the given name.
+
+```sql
+CREATE VIEW interesting_stacks AS
+SELECT stack_id, depth
+FROM slice WHERE name LIKE "%interesting slice name%";
+
+SELECT
+ *
+FROM
+ interesting_stacks LEFT JOIN
+ descendant_slice_by_stack(interesting_stacks.stack_id) AS descendant
+ ON descendant.depth = interesting_stacks.depth + 1
+```
+
### Connected/Following/Preceding flows
DIRECTLY_CONNECTED_FLOW, FOLLOWING_FLOW and PRECEDING_FLOW are custom operator
diff --git a/docs/concepts/config.md b/docs/concepts/config.md
index 99f4cbc..43082b0 100644
--- a/docs/concepts/config.md
+++ b/docs/concepts/config.md
@@ -424,10 +424,6 @@
Example config:
```protobuf
-# If no trigger is hit, the trace will end without having recorded any data
-# after 30s.
-trigger_timeout_ms: 30000
-
# If the "myapp_is_slow" is hit, the trace starts recording data and will be
# stopped after 5s.
trigger_config {
@@ -436,6 +432,9 @@
name: "myapp_is_slow"
stop_delay_ms: 5000
}
+ # If no trigger is hit, the trace will end without having recorded any data
+ # after 30s.
+ trigger_timeout_ms: 30000
}
# The rest of the config is as usual.
diff --git a/docs/contributing/build-instructions.md b/docs/contributing/build-instructions.md
index 9eba8f2..ed5f135 100644
--- a/docs/contributing/build-instructions.md
+++ b/docs/contributing/build-instructions.md
@@ -30,7 +30,7 @@
#### Pull dependent libraries and toolchains
```bash
-tools/install-build-deps [--android] [--ui]
+tools/install-build-deps [--android] [--ui] [--linux-arm]
```
`--android` will pull the Android NDK, emulator and other deps required
@@ -39,6 +39,8 @@
`--ui` will pull NodeJS and all the NPM modules required to build the
Web UI. See the [UI Development](#ui-development) section below for more.
+`--linux-arm` will pull the sysroots for cross-compiling for Linux ARM/64.
+
#### Generate the build files via GN
Perfetto uses [GN](https://gn.googlesource.com/gn/+/HEAD/docs/quick_start.md)
@@ -46,7 +48,7 @@
more.
```bash
-tools/gn args out/android`
+tools/gn args out/android
```
This will open an editor to customize the GN args. Enter:
@@ -154,10 +156,11 @@
## Supported platforms
-**Linux desktop** (Debian Rodete)
+**Linux desktop** (Debian Testing/Rodete)
- Hermetic clang + libcxx toolchain (both following chromium's revisions)
- GCC-7 and libstdc++ 6
+- Cross-compiling for arm and arm64 (more below).
**Android**
@@ -240,6 +243,39 @@
python3 tools/ninja -C out/win perfetto traced trace_processor_shell
```
+### Cross-compiling for Linux ARM/64
+
+When cross-compiling for Linux you will need a sysroot. You have two options:
+
+#### 1. Use the built-in sysroots based on Debian Sid
+
+```bash
+tools/install-build-deps --linux-arm
+```
+
+Then set the following GN args:
+
+```python
+target_os = "linux"
+target_cpu = "arm"
+# or
+target_cpu = "arm64"
+```
+
+#### 2. Use your own sysroot
+
+In this case you need to manually specify the sysroot location and the
+toolchain prefix triplet to use.
+
+```python
+target_os = "linux"
+target_sysroot = "/path/to/sysroot"
+target_triplet = "aarch64-linux-gnu" # Or any other supported triplet.
+```
+
+For more details see the [Using cutom toolchains](#custom-toolchain) section
+below.
+
## Build configurations
TIP: `tools/build_all_configs.py` can be used to generate out/XXX folders for
diff --git a/docs/contributing/sdk-releasing.md b/docs/contributing/sdk-releasing.md
index baccd05..9679382 100644
--- a/docs/contributing/sdk-releasing.md
+++ b/docs/contributing/sdk-releasing.md
@@ -15,7 +15,7 @@
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).
+release (cherry-picks on the releases/vN.x branch).
Continue with the appropriate section below.
@@ -54,6 +54,24 @@
git merge <sha1>
```
+Update the CHANGELOG with a dedicated entry for the new minor version.
+This is important because the
+[write_version_header.py](/tools/write_version_header.py) script, which is
+invoked by the build system, looks at the CHANGELOG to work out the latest
+v${maj}.${min} version.
+
+For an example see [r.android.com/1730332](https://r.android.com/1730332)
+
+```txt
+v16.1 - 2021-06-08:
+ Tracing service and probes:
+ * Cherry-pick of r.android.com/1716718 which missed the v16 branch ... .
+
+
+v16.0 - 2021-06-01:
+ ...
+```
+
## Building and tagging the release
1. Generate and commit the amalgamated source files.
diff --git a/docs/contributing/testing.md b/docs/contributing/testing.md
index 98f0812..6eabc54 100644
--- a/docs/contributing/testing.md
+++ b/docs/contributing/testing.md
@@ -124,6 +124,35 @@
be ignored (for example,
`SELECT RUN_METRIC('metric file') as surpress_query_output`)
+UI pixel diff tests
+-----------------
+The pixel tests are used to ensure core user journeys work by verifying they
+are the same pixel to pixel against a golden screenshot. They use a headless
+chrome to load the webpage and take a screenshot and compare pixel by pixel a
+golden screenshot. You can run these tests by using `ui/run-integrationtests`.
+
+
+These test fail when a certain number of pixels are different. If these tests
+fail, you'll need to investigate the diff and determine if its intentional. If
+its a desired change you will need to update the screenshots on a linux machine
+to get the CI to pass. You can update them by generating and uploading a new
+baseline (this requires access to a google bucket through gcloud which only
+googlers have access to, googlers can install gcloud
+[here](https://g3doc.corp.google.com/cloud/sdk/g3doc/index.md#installing-and-using-the-cloud-sdk)).
+
+```
+ui/run-integrationtests --rebaseline
+tools/add_test_data test/data/ui-screenshots
+```
+
+Once finished you can commit and upload as part of your CL to cause the CI to
+use your new screenshots.
+
+NOTE: If you see a failing diff test you can see the pixel differences on the CI
+by using the link to the UI and replace `/ui/index.html` with
+`/ui-test-artifacts/<name_of_failing_png_test_from_logs>.png`. This allows you
+to tell where in the picture the change was introduced.
+
Android CTS tests
-----------------
CTS tests ensure that any vendors who modify Android remain compliant with the
diff --git a/docs/data-sources/native-heap-profiler.md b/docs/data-sources/native-heap-profiler.md
index ca9e6c8..47c3122 100644
--- a/docs/data-sources/native-heap-profiler.md
+++ b/docs/data-sources/native-heap-profiler.md
@@ -70,7 +70,7 @@
#### Using the Recording page of Perfetto UI
-You can also use the [Perfetto UI](https://ui.perfetto.dev/#!/record?p=memory)
+You can also use the [Perfetto UI](https://ui.perfetto.dev/#!/record/memory)
to record heapprofd profiles. Tick "Heap profiling" in the trace configuration,
enter the processes you want to target, click "Add Device" to pair your phone,
and record profiles straight from your browser. This is also possible on
@@ -116,6 +116,8 @@
gets attributed the complete n bytes. For more accuracy, allocations larger than
the sampling interval bypass the sampling logic and are recorded with their true
size.
+See the [heapprofd Sampling](/docs/design-docs/heapprofd-sampling) document for
+details.
## Startup profiling
diff --git a/docs/design-docs/pivot-tables.md b/docs/design-docs/pivot-tables.md
new file mode 100644
index 0000000..ddc340c
--- /dev/null
+++ b/docs/design-docs/pivot-tables.md
@@ -0,0 +1,206 @@
+# Pivot Tables
+
+_**Project Plan**: [Perfetto: Pivot tables for slices](https://docs.google.com/document/d/1RuEGQKLgOA8YWjZJHD6CTA3ghRRg6o5Phg3_rFCJEDE/)_
+_**How to Use**: [Pivot Table Usage](/docs/visualization/perfetto-ui#pivot-tables)_
+_**For Googlers**: [Perfetto: Pivot Table Use Cases](https://docs.google.com/document/d/1_iR-JjD7m19Q9GQtMk1_5NLSYXFicB_gg4S9D-6Q8lU/)_
+
+## Objective
+Pivot tables give a simplified aggregated view of more complex data. They are
+made up of a number of pivots and aggregations that are grouped around these
+pivots. You can add more columns/aggregations and drag and drop the columns to
+explore the underlying data.
+
+## Motivation
+Pivot tables are useful in debugging hangs, stalls, and digging into traces
+which usually have too much data to clearly see the problems.
+The pivot table allows users to create custom tables to view specific
+information about traces in a summarized and less complex way.
+
+## Main Components
+
+
+
+### Details Panel (Frontend)
+The [DetailsPanel](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/details_panel.ts)
+searches for active PivotTables to display on screen. It also syncs the
+PivotTableHelper with data from the State. (PivotTableHelper only syncs when the
+PivotTableEditor modal is not open).
+
+
+### Pivot Table (Frontend)
+The [PivotTable](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/pivot_table.ts) builds
+the pivot table tab and the table. It also handles user requests (like opening
+the pivot table editor, drag and drop columns, expand, etc) by calling the
+PivotTableHelper and updating the table.
+
+
+### PivotTableEditor (Frontend)
+The [PivotTableEditor](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/pivot_table_editor.ts)
+consists of ColumnPicker and ColumnDisplay classes.
+ColumnPicker allows the user to select column type, name and aggregation. Edits
+made through the ColumnPicker are saved temporarily in the PivotTableHelper
+without updating the state.
+ColumnDisplay displays the selected column from the ColumnPicker, it also allows
+users to manipulate the columns after selection (like delete, reorder, change
+the default sorting, etc...).
+In this stage the user is able to query the selected columns and update the
+table or discard the changes made and the PivotTableHelper will resync with the
+data in state.
+
+
+### PivotTableHelper (Frontend)
+The [PivotTableHelper](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/pivot_table_helper.ts)
+is created by every PivotTableController for every PivotTableId. It stores a
+copy of the selectedPivots and selectedAggregations from state. It also holds
+the logic for manipulating the data locally, which are used by the PivotTable
+and PivotTableEditor.
+It also replaces the data in the State with the changes upon request.
+The PivotTableHelper also checks for special “stack” columns, called stackPivots
+(`name (stack)` for [slice table](/docs/analysis/sql-tables.autogen#slice) is
+currently the only special column), as it sets the column attributes which are
+then used to identify them by other components.
+
+
+### State (Common)
+[PivotTableState](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/common/state.ts;l=303) holds the
+information that needs to be transferred to and from the frontend and the
+controller for each pivot table instance (PivotTableId). It also includes the
+global PivotTableConfigs (like the availableColumns and availableAggregations).
+
+
+### PivotTableController (Controller)
+A new [PivotTableController](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/controller/pivot_table_controller.ts)
+is created for every PivotTableId.
+The PivotTableController handles the setup of the pivot table once added, it
+queries for the columns for all tables and sets the PivotTableConfig. It also
+creates and initializes a PivotTableHelper for every PivotTableId and publishes
+it to the frontend.
+Additionally, the PivotTableController handles the collection and the
+computation of all data needed by the PivotTableQueryGenerator.
+It constantly checks if a request has been set in the PivotTableState and acts
+on it if so.
+It decides what columns to query, what whereFilters and tables to include and
+how to reformat the query result into a PivotTableQueryResponse based on the
+request type.
+
+There are four types of requests implemented in the controller:
+
+**_QUERY:_**
+Queries the first pivot of the selectedPivots and all the aggregations,
+including any global or table-wide whereFilters (Like the start and end
+timestamp and selected track_ids that are set by the pivot table generated
+through area selection).
+It also adds a whereFilter (Filter in the where clause of the query) if the
+pivot is a stackPivot to restrict the result to the top level slices only, since
+descendants can be generated by expanding the cell and issuing the DESCENDANTS
+request, and returns the result as a PivotTableQueryResponse.
+
+
+
+Returned PivotTableQueryResponse:
+
+```typescript
+pivotTableQueryResponse = {
+ columns: ['slice type', 'slice category', 'slice name'];
+ rows: [
+ {
+ row: 'internal_slice',
+ expandableColumns: ['slice type'],
+ expandedRows = [],
+ }, {
+ row: 'thread_slice',
+ expandableColumns: ['slice type'],
+ expandedRows = [],
+ };
+ ]
+}
+```
+
+**_EXPAND:_**
+The [PivotTableBody](https://cs.android.com/android/_/android/platform/external/perfetto/+/a9118d769009349da7f264abb392f4207e66602b:ui/src/frontend/pivot_table.ts;l=235;drc=0bc8ff07f372a58ca4d0399d88567a66ef5b591b) generates the nested structure by
+recursively displaying the rows and checking if the row contains any expanded
+rows with the isExpanded flag set to true. As it goes through the nested rows,
+it passes the row index that it's about to expand, along with the column it's
+expanding for till it reaches a [PivotTableRow](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/pivot_table.ts;l=192).
+The PivotTableRow creates a cell for each column. If the cell is at a column
+that can be expanded, it is created as an [ExpandableCell](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/pivot_table.ts;l=121).
+When an 'EXPAND' request is issued on an ExpandableCell, it sets the
+requestedAction in the PivotTableState and provides it with the SubQueryAttrs.
+
+Given a columnIdx, value, and an array of rowIndicies (SubQueryAttrs) from
+the requestedAction in the PivotTableState, it finds the exact row that called
+this request from the main PivotTableQueryResponse, and finds the next pivot
+to query. It then generates the query similarly to the ‘QUERY’ request, but
+includes the whereFilter of the previous column (column name = column value).
+The rows of the query result are then nested into the caller row’s expandedRows,
+to build a tree view structure while expanding.
+
+
+
+Passed value:
+
+```typescript
+subQueryAttrs = {
+ rowIndices: [0, 3],
+ columnIdx: 1,
+ value: 'blink,benchmark',
+ expandedRowColumns: ['slice category'],
+}
+```
+
+Returned expanded rows:
+
+```typescript
+rows = [
+ {
+ row: 'LocalFrameView::RunAccessibilityLifecyclePhase',
+ expandableColumns: [],
+ expandedRows: []
+ },
+ {
+ row: 'LocalFrameView::RunCompositingInputsLifecyclePhase',
+ expandableColumns: [],
+ expandedRows: []
+ },
+ {
+ row: 'LocalFrameView::RunStyleAndLayoutLifecyclePhases',
+ expandableColumns: [],
+ expandedRows: []
+ },
+ ...
+]
+```
+
+The returned rows are saved inside the caller row expandedRows map.
+
+```typescript
+rows = {
+ row: 'blink,benchmark',
+ expandableColumns: ['slice category'],
+ expandedRows: [
+ 'slice name' => {
+ isExpanded: true,
+ rows
+ }
+ ]
+}
+```
+
+**_UNEXPAND:_**
+Sets the caller row’s isExpanded flag to false, to hide it from the display but
+also keeping its expandedRows saved so as to not have to query them again if
+requested.
+
+**_DESCENDANTS:_**
+Should only be called for stackPivots, generates a query containing the
+stackPivot and the next pivot, if it exists, and all the aggregations. It also
+requests the PivotTableQueryGenerator to order by depth first, which is then
+used to refactor the resulting rows into the PivotTableQueryResponse tree view
+structure.
+The returned format is similar to the EXPAND request.
+
+### PivotTableQueryGenerator (Common)
+[PivotTableQueryGenerator](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/common/pivot_table_query_generator.ts)
+generates an sql query based on the given data, along with any hidden columns
+that may need to be added. It also creates an alias for each pivot and
+aggregation that is used to identify the resulting cells in the rows.
diff --git a/docs/images/pivot-tables/pivot-table-area-selection.png b/docs/images/pivot-tables/pivot-table-area-selection.png
new file mode 100644
index 0000000..f2c84d3
--- /dev/null
+++ b/docs/images/pivot-tables/pivot-table-area-selection.png
Binary files differ
diff --git a/docs/images/pivot-tables/pivot-table-design.png b/docs/images/pivot-tables/pivot-table-design.png
new file mode 100644
index 0000000..e38da25
--- /dev/null
+++ b/docs/images/pivot-tables/pivot-table-design.png
Binary files differ
diff --git a/docs/images/pivot-tables/pivot-table-editor.png b/docs/images/pivot-tables/pivot-table-editor.png
new file mode 100644
index 0000000..8db7ff9
--- /dev/null
+++ b/docs/images/pivot-tables/pivot-table-editor.png
Binary files differ
diff --git a/docs/images/pivot-tables/pivot-table-expanded-cell.png b/docs/images/pivot-tables/pivot-table-expanded-cell.png
new file mode 100644
index 0000000..4628272
--- /dev/null
+++ b/docs/images/pivot-tables/pivot-table-expanded-cell.png
Binary files differ
diff --git a/docs/images/pivot-tables/pivot-table-query.png b/docs/images/pivot-tables/pivot-table-query.png
new file mode 100644
index 0000000..e50ae9d
--- /dev/null
+++ b/docs/images/pivot-tables/pivot-table-query.png
Binary files differ
diff --git a/docs/images/pivot-tables/pivot-table.png b/docs/images/pivot-tables/pivot-table.png
new file mode 100644
index 0000000..3e842f9
--- /dev/null
+++ b/docs/images/pivot-tables/pivot-table.png
Binary files differ
diff --git a/docs/instrumentation/tracing-sdk.md b/docs/instrumentation/tracing-sdk.md
index cc4e6c4..1e58bb8 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 v17.0
```
The SDK consists of two files, `sdk/perfetto.h` and `sdk/perfetto.cc`. These are
diff --git a/docs/quickstart/android-tracing.md b/docs/quickstart/android-tracing.md
index 3d3b37e..f27fe7f 100644
--- a/docs/quickstart/android-tracing.md
+++ b/docs/quickstart/android-tracing.md
@@ -84,14 +84,16 @@
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
+./record_android_trace -o trace_file.perfetto-trace -t 10s -b 32mb \
+sched freq idle am wm gfx view binder_driver hal dalvik camera input res memory
```
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
+python3 record_android_trace -o trace_file.perfetto-trace -t 10s -b 32mb \
+sched freq idle am wm gfx view binder_driver hal dalvik camera input res memory
```
**Using the on-device /system/bin/perfetto command**
@@ -99,7 +101,8 @@
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
+adb shell perfetto -o /data/misc/perfetto-traces/trace_file.perfetto-trace -t 20s \
+sched freq idle am wm gfx view binder_driver hal dalvik camera input res memory
```
Caveats when using directly the `adb shell perfetto` workflow:
diff --git a/docs/quickstart/linux-tracing.md b/docs/quickstart/linux-tracing.md
index 104b02e..d60822a 100644
--- a/docs/quickstart/linux-tracing.md
+++ b/docs/quickstart/linux-tracing.md
@@ -21,7 +21,7 @@
3. Generate the build configuration
```bash
-tools/gn gn gen --args='is_debug=false' out/linux
+tools/gn gen --args='is_debug=false' out/linux
# Or use `tools/build_all_configs.py` to generate more build configs.
```
@@ -73,7 +73,7 @@
3. Detach from the tmux session with `Ctrl-B D`,or shut it down with
`tmux kill-session -t demo`. The script will then copy the trace to
- `/tmp/trace.protobuf`, as a binary-encoded protobuf (see
+ `/tmp/trace.perfetto-trace`, as a binary-encoded protobuf (see
[TracePacket reference](/docs/reference/trace-packet-proto.autogen)).
## Visualizing the trace
@@ -87,7 +87,7 @@
1. Navigate to [ui.perfetto.dev](https://ui.perfetto.dev) in a browser.
2. Click the **Open trace file** on the left-hand menu, and load the captured
- trace (by default at `/tmp/trace.protobuf`).
+ trace (by default at `/tmp/trace.perfetto-trace`).
3. Explore the trace by zooming/panning using WASD, and mouse for expanding
process tracks (rows) into their constituent thread tracks.
diff --git a/docs/toc.md b/docs/toc.md
index b9f8b9c..565ee8d 100644
--- a/docs/toc.md
+++ b/docs/toc.md
@@ -72,6 +72,8 @@
* [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)
+ * [Pivot tables](design-docs/pivot-tables.md)
* [ProtoZero](design-docs/protozero.md)
* [Security model](design-docs/security-model.md)
* [Statsd Checkpoint Atoms](design-docs/checkpoint-atoms.md)
+
diff --git a/docs/visualization/perfetto-ui-release-process.md b/docs/visualization/perfetto-ui-release-process.md
index a154a32..c92f185 100644
--- a/docs/visualization/perfetto-ui-release-process.md
+++ b/docs/visualization/perfetto-ui-release-process.md
@@ -1,17 +1,29 @@
# Perfetto UI Release Process
-The UI has three release channels which are configured by the [channels.json](https://github.com/google/perfetto/blob/master/ui/release/channels.json) file. The channels are:
-- `stable`, the version visitors to ui.perfetto.dev received by default. Updated every four weeks.
+The UI has three release channels which are configured by the
+[channels.json](/ui/release/channels.json) file. The channels are:
+
+- `stable`, the version served by default on ui.perfetto.dev.
+ Updated every four weeks.
- `canary`, a less stable but fresher release. Updated every 1-2 weeks.
- `autopush`, the current HEAD version of the UI. Unstable.
The release process is based around a four week cycle.
-- Week 1: Update `canary` to `HEAD`
-- Week 2: Update `canary` to `HEAD`
-- Week 3: Cherry-pick bug fixes to `canary`
-- Week 4: Update `stable` to current `canary`, update `canary` to `HEAD`
+
+- Week 1: Update `canary` to `HEAD`.
+- Week 2: Update `canary` to `HEAD`.
+ Canary stabilization week 1/2 starts here.
+ Only critical bug fixes can be cherry-picked onto `canary`.
+- Week 3: Canary stabilization week 2/2.
+- Week 4: Update `stable` to current `canary`, update `canary` to `HEAD`.
After the fourth week the cycle repeats from week one.
+This is so that:
+
+- Canary soaks for two weeks before being promoted to stable.
+- Newer features can be tried out in Canary within a week, or two at most (if
+ in the stabilization weeks).
+- Stable users aren't disrupted more than once per month.
## Changing release channel
@@ -35,5 +47,58 @@

-Clicking on the version number takes you to Github where you can see which commits are part of this version. The version number format is `v<Perfetto version>.0.<Commits since that version>`.
+Clicking on the version number takes you to Github where you can see which commits are part of this version. The version number format is `v<maj>.<min>.<Commit SHA1 prefix>` where `<maj>.<min>` are extracted from the top entry in the
+[CHANGELOG](/CHANGELOG).
+## Cherry-picking a change
+
+If a change needs to be backported onto canary or stable branches, do the
+following:
+
+```bash
+git fetch origin
+git co -b ui-canary -t origin/ui-canary
+git cherry-pick -x $SHA1_OF_ORIGINAL_CL
+git cl upload
+
+# Repeat for origin/ui-stable branch if needed.
+```
+
+Once the cherry-picks are landed, send out a CL to update the
+[channels.json](/ui/release/channels.json) in the `master` branch. See
+[r.android.com/1726101](https://r.android.com/1726101) for an example.
+
+```json
+{
+ "channels": [
+ {
+ "name": "stable",
+ "rev": "6dd6756ffbdff4f845c4db28e1fd5aed9ba77b56"
+ // ^ This should point to the HEAD of origin/ui-stable.
+ },
+ {
+ "name": "canary",
+ "rev": "3e21f613f20779c04b0bcc937f2605b9b05556ad"
+ // ^ This should point to the HEAD of origin/ui-canary.
+ },
+ {
+ "name": "autopush",
+ "rev": "HEAD"
+ // ^ Don't touch this one.
+ }
+ ]
+}
+```
+
+The state of `channels.json` in the other branches is irrelevant, the release
+infrastructure only looks at the `master` branch to determine the pinning of
+each channel.
+
+After the `channels.json` CL lands, the build infrastructure will pick it up
+and update ui.perfetto.dev within ~30 mins.
+
+Googlers: You can check build progress and logs on
+[go/perfetto-ui-build-status](http://go/perfetto-ui-build-status). See also
+[go/perfetto-ui-autopush](http://go/perfetto-ui-autopush) and
+[go/perfetto-ui-channels](http://go/perfetto-ui-channels) for the design docs of
+the serving infrastructure.
diff --git a/docs/visualization/perfetto-ui.md b/docs/visualization/perfetto-ui.md
index 426f2dc..a3f16ba 100644
--- a/docs/visualization/perfetto-ui.md
+++ b/docs/visualization/perfetto-ui.md
@@ -71,3 +71,25 @@
Note: There is no equivalent debug counters feature yet, but the feature request
is tracked on [b/168886909](http://b/168886909)).
+
+### Pivot Tables
+
+To use pivot tables in the Perfetto UI, you will need to enable the
+"Pivot tables" feature flag in the "Flags" tab under "Support" in the Sidebar.
+You can pop up a pivot table over the entire trace when clicking "p" on your
+keyboard. The "Edit" button opens a pop up window to add/remove and reorder
+columns and change the default sorting of aggregations.
+
+
+
+Clicking on "Query" generates a table with the selected columns.
+Table cells with the expand icon can be expanded to show the next column values.
+The "name (stack)" column displays top level slices that can be expanded to show
+their descendants down to the last child.
+
+
+
+Area selection pops up a pre-filled pivot table restricted over the selected
+timestamps and track ids.
+
+
diff --git a/examples/sdk/README.md b/examples/sdk/README.md
index 3b8295f..01f3eb1 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 v17.0
```
Then, build using CMake:
@@ -98,7 +98,7 @@
> Tip: You can generate a new trace config with additional data sources using
> the [Perfetto UI](https://ui.perfetto.dev/#!/record) and replace
> `system_wide_trace_cfg.pbtxt` with the [generated config](
-> https://ui.perfetto.dev/#!/record?p=instructions).
+> https://ui.perfetto.dev/#!/record/instructions).
## Custom data source example
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index 15fa31b..92f1107 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -43,6 +43,9 @@
perfetto_force_dlog_on = perfetto_force_dlog == "on"
perfetto_force_dlog_off = perfetto_force_dlog == "off"
+ perfetto_force_dcheck_on = perfetto_force_dcheck == "on"
+ perfetto_force_dcheck_off = perfetto_force_dcheck == "off"
+
# We can't just use (is_linux || is_android) in perfetto.gni because that
# doesn't work in Android Mac host builds. We lose the GN notion of OS once
# we run the tools/gen_xxx generators.
@@ -71,6 +74,8 @@
"PERFETTO_COMPONENT_BUILD=$perfetto_component_build",
"PERFETTO_FORCE_DLOG_ON=$perfetto_force_dlog_on",
"PERFETTO_FORCE_DLOG_OFF=$perfetto_force_dlog_off",
+ "PERFETTO_FORCE_DCHECK_ON=$perfetto_force_dcheck_on",
+ "PERFETTO_FORCE_DCHECK_OFF=$perfetto_force_dcheck_off",
"PERFETTO_VERBOSE_LOGS=$perfetto_verbose_logs_enabled",
"PERFETTO_VERSION_GEN=$enable_perfetto_version_gen",
"PERFETTO_TP_PERCENTILE=$enable_perfetto_trace_processor_percentile",
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index d7263e7..c6817aa 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -217,6 +217,16 @@
# console.
perfetto_force_dlog = perfetto_force_dlog_default
+ # Whether DCHECKs should be enabled or not. Values: "on" | "off" | "".
+ # By default ("") DCHECKs are enabled only:
+ # - If DCHECK_ALWAYS_ON is defined (which is mainly a Chromium-ism).
+ # - On debug builds (i.e. if NDEBUG is NOT defined) but only in Chromium,
+ # Android and standalone builds.
+ # - On all other builds (e.g., SDK) it's off regardless of NDEBUG (unless
+ # DCHECK_ALWAYS_ON is defined).
+ # See base/logging.h for the implementation of all this.
+ perfetto_force_dcheck = ""
+
# 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.
@@ -262,7 +272,8 @@
# Enables httpd RPC support in the trace processor.
# Further per-OS conditionals are applied in gn/BUILD.gn.
enable_perfetto_trace_processor_httpd =
- enable_perfetto_trace_processor && perfetto_build_standalone
+ enable_perfetto_trace_processor &&
+ (perfetto_build_standalone || perfetto_build_with_android)
# Enables Zlib support. This is used both by the "perfetto" cmdline client
# (for compressing traces) and by trace processor (for compressed traces).
diff --git a/gn/standalone/BUILD.gn b/gn/standalone/BUILD.gn
index ffe5725..6660963 100644
--- a/gn/standalone/BUILD.gn
+++ b/gn/standalone/BUILD.gn
@@ -81,6 +81,7 @@
"-Wno-padded",
"-Wno-poison-system-directories",
"-Wno-reserved-id-macro",
+ "-Wno-reserved-identifier",
"-Wno-unknown-sanitizers",
"-Wno-unknown-warning-option",
]
diff --git a/gn/standalone/toolchain/BUILD.gn b/gn/standalone/toolchain/BUILD.gn
index ca8f247..8dba119 100644
--- a/gn/standalone/toolchain/BUILD.gn
+++ b/gn/standalone/toolchain/BUILD.gn
@@ -49,6 +49,8 @@
# 2. setting is_system_compiler=true in args.gn and the env vars AR/CC/CXX.
# This is used by OSSFuzz and CrOS ebuilds.
+_llvm_strip_wrapper = rebase_path("llvm-strip.py", root_build_dir)
+
declare_args() {
sysroot = ""
gcc_toolchain = ""
@@ -58,7 +60,15 @@
if (is_linux_host) {
linker = "gold"
- strip = "strip"
+ if (linux_llvm_objcopy != "") {
+ # If we are using the hermetic clang toolchain llvm-objcopy from there as
+ # it works with Linux-arm cross toolchains. The |_llvm_strip_wrapper| is
+ # to set argv0 as llvm-strip. llvm-objcopy's frontend works differently
+ # when invoked as llvm-strip, pretending to be just 'strip'.
+ strip = "${_llvm_strip_wrapper} ${linux_llvm_objcopy}"
+ } else {
+ strip = "strip"
+ }
} else if (is_mac_host) {
strip = "strip -x"
}
@@ -90,7 +100,7 @@
# Then determine the target toolchain.
declare_args() {
- target_sysroot = sysroot
+ _default_target_sysroot = ""
target_gcc_toolchain = ""
# |target_triplet| is the variable that the user can set via GN args. The user
@@ -111,8 +121,12 @@
_target_triplet = "i686-apple-darwin"
} else if (target_os == "linux" && target_cpu == "arm64") {
_target_triplet = "aarch64-linux-gnu"
+ _default_target_sysroot =
+ rebase_path("//buildtools/debian_sid_arm64-sysroot", root_build_dir)
} else if (target_os == "linux" && target_cpu == "arm") {
- _target_triplet = "arm-linux-gnueabi"
+ _target_triplet = "arm-linux-gnueabihf"
+ _default_target_sysroot =
+ rebase_path("//buildtools/debian_sid_arm-sysroot", root_build_dir)
} else if (target_os == "linux" && target_cpu == "x64") {
_target_triplet = "x86_64-linux-gnu"
} else if (target_os == "linux" && target_cpu == "x86") {
@@ -133,6 +147,17 @@
}
declare_args() {
+ if (sysroot != "") {
+ # If the user specifies a sysroot, use that for both host and target.
+ target_sysroot = sysroot
+ } else {
+ # If no explicit sysroot has been set, use the guessed sysroot from the ones
+ # pulled by //tools/install-build-deps (only for Linux).
+ target_sysroot = _default_target_sysroot
+ }
+}
+
+declare_args() {
target_strip = ""
if (is_linux || is_android) {
target_linker = "gold"
@@ -158,6 +183,7 @@
} else {
assert(_target_triplet != "",
"target_triplet must be non-empty when cross-compiling")
+ target_strip = strip
if (is_clang) {
if (is_linux_host) {
target_cc = "${linux_clang_bin} --target=${_target_triplet}"
diff --git a/gn/standalone/toolchain/llvm-strip.py b/gn/standalone/toolchain/llvm-strip.py
new file mode 100755
index 0000000..bc2b7d8
--- /dev/null
+++ b/gn/standalone/toolchain/llvm-strip.py
@@ -0,0 +1,34 @@
+#!/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.
+"""This is really a wrapper around exec() for llvm-objcopy.
+
+It is used to execute llvm-objcopy passing "llvm-strip" as argv0. This is
+because llvm-objcopy frontend behaves differently and emulates the "strip"
+binary when its argv0 is set as llvm-strip.
+"""
+
+import os
+import sys
+
+
+def main():
+ if (len(sys.argv) < 3):
+ sys.stderr.write('Usage: %s /path/to/llvm-objcopy [args]\n' % (__file__))
+ return 1
+ os.execlp(sys.argv[1], "llvm-strip", *sys.argv[2:])
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/gn/standalone/toolchain/llvm.gni b/gn/standalone/toolchain/llvm.gni
index e3fc350..75bc5ff 100644
--- a/gn/standalone/toolchain/llvm.gni
+++ b/gn/standalone/toolchain/llvm.gni
@@ -20,12 +20,14 @@
assert(!is_hermetic_clang || is_clang, "is_hermetic_clang requires is_clang")
+linux_llvm_objcopy = ""
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_llvm_objcopy = "$_hermetic_llvm_dir/bin/llvm-objcopy"
linux_clang_linker = "lld"
} else if (is_clang && !is_system_compiler) {
# Guess the path for the system clang.
diff --git a/heapprofd.rc b/heapprofd.rc
index bf313b1..d63e3be 100644
--- a/heapprofd.rc
+++ b/heapprofd.rc
@@ -19,7 +19,7 @@
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
+ task_profiles ProcessCapacityHigh
onrestart exec_background - nobody shell -- /system/bin/heapprofd --cleanup-after-crash
# DAC_READ_SEARCH is denied by SELinux on user builds because the SELinux
# permission is userdebug_or_eng only.
@@ -35,7 +35,7 @@
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
+ task_profiles ProcessCapacityHigh
# DAC_READ_SEARCH is denied by SELinux on user builds because the SELinux
# permission is userdebug_or_eng only.
capabilities KILL DAC_READ_SEARCH
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 649d9ed..2867007 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
@@ -30,11 +30,13 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPONENT_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DCHECK_ON() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DCHECK_OFF() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERBOSE_LOGS() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (1)
#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_HTTPD() (1)
#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_ZLIB() (1)
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 393c2b2..e08a103 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -30,6 +30,8 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPONENT_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DCHECK_ON() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DCHECK_OFF() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERBOSE_LOGS() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (1)
diff --git a/include/perfetto/base/logging.h b/include/perfetto/base/logging.h
index 8641a1c..6e128be 100644
--- a/include/perfetto/base/logging.h
+++ b/include/perfetto/base/logging.h
@@ -29,12 +29,17 @@
#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.
-#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
-#define PERFETTO_DCHECK_IS_ON() 0
-#else
+#if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DCHECK_ON)
#define PERFETTO_DCHECK_IS_ON() 1
+#elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DCHECK_OFF)
+#define PERFETTO_DCHECK_IS_ON() 0
+#elif defined(DCHECK_ALWAYS_ON) || \
+ (!defined(NDEBUG) && (PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) || \
+ PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD) || \
+ PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)))
+#define PERFETTO_DCHECK_IS_ON() 1
+#else
+#define PERFETTO_DCHECK_IS_ON() 0
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_ON)
diff --git a/include/perfetto/ext/base/file_utils.h b/include/perfetto/ext/base/file_utils.h
index bf33d70..5920196 100644
--- a/include/perfetto/ext/base/file_utils.h
+++ b/include/perfetto/ext/base/file_utils.h
@@ -21,10 +21,13 @@
#include <stddef.h>
#include <string>
+#include <vector>
#include "perfetto/base/build_config.h"
#include "perfetto/base/export.h"
+#include "perfetto/base/status.h"
#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/utils.h"
namespace perfetto {
@@ -78,6 +81,21 @@
// Wrapper around access(path, F_OK).
bool FileExists(const std::string& path);
+// Gets the extension for a filename. If the file has two extensions, returns
+// only the last one (foo.pb.gz => .gz). Returns empty string if there is no
+// extension.
+std::string GetFileExtension(const std::string& filename);
+
+// Puts the path to all files under |dir_path| in |output|, recursively walking
+// subdirectories. File paths are relative to |dir_path|. Only files are
+// included, not directories. Path separator is always '/', even on windows (not
+// '\').
+base::Status ListFilesRecursive(const std::string& dir_path,
+ std::vector<std::string>& output);
+
+// Returns the size of the file at `path` or nullopt in case of error.
+Optional<size_t> GetFileSize(const std::string& path);
+
} // namespace base
} // namespace perfetto
diff --git a/include/perfetto/ext/base/string_utils.h b/include/perfetto/ext/base/string_utils.h
index bd4f1f6..5b687eb 100644
--- a/include/perfetto/ext/base/string_utils.h
+++ b/include/perfetto/ext/base/string_utils.h
@@ -17,20 +17,18 @@
#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
#define INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
+#include <stdlib.h>
+
+#include <cinttypes>
#include <string>
#include <vector>
-#include <inttypes.h>
-#include <stdlib.h>
-
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/string_view.h"
namespace perfetto {
namespace base {
-std::string QuoteAndEscapeControlCodes(const std::string& raw);
-
inline char Lowercase(char c) {
return ('A' <= c && c <= 'Z') ? static_cast<char>(c - ('A' - 'a')) : c;
}
@@ -97,6 +95,8 @@
bool StartsWith(const std::string& str, const std::string& prefix);
bool EndsWith(const std::string& str, const std::string& suffix);
+bool StartsWithAny(const std::string& str,
+ const std::vector<std::string>& prefixes);
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);
diff --git a/include/perfetto/ext/base/string_view.h b/include/perfetto/ext/base/string_view.h
index 4f16f90..83c7ea6 100644
--- a/include/perfetto/ext/base/string_view.h
+++ b/include/perfetto/ext/base/string_view.h
@@ -118,6 +118,20 @@
#endif
}
+ bool StartsWith(const StringView& other) {
+ if (other.size() == 0)
+ return true;
+ if (size() == 0)
+ return false;
+ if (other.size() > size())
+ return false;
+ for (uint32_t i = 0; i < other.size(); ++i) {
+ if (at(i) != other.at(i))
+ return false;
+ }
+ return true;
+ }
+
std::string ToStdString() const {
return size_ == 0 ? "" : std::string(data_, size_);
}
diff --git a/include/perfetto/ext/base/string_writer.h b/include/perfetto/ext/base/string_writer.h
index cee3198..7005e3b 100644
--- a/include/perfetto/ext/base/string_writer.h
+++ b/include/perfetto/ext/base/string_writer.h
@@ -17,9 +17,9 @@
#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_WRITER_H_
#define INCLUDE_PERFETTO_EXT_BASE_STRING_WRITER_H_
-#include <inttypes.h>
-#include <math.h>
#include <string.h>
+
+#include <cinttypes>
#include <cmath>
#include <cstdlib>
#include <limits>
diff --git a/include/perfetto/ext/tracing/core/tracing_service.h b/include/perfetto/ext/tracing/core/tracing_service.h
index c26d949..9636cdf 100644
--- a/include/perfetto/ext/tracing/core/tracing_service.h
+++ b/include/perfetto/ext/tracing/core/tracing_service.h
@@ -42,7 +42,7 @@
class TraceWriter;
// Exposed for testing.
-extern const char* kBugreportTracePath;
+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.
diff --git a/include/perfetto/profiling/parse_smaps.h b/include/perfetto/profiling/parse_smaps.h
index e6c260c..9623c38 100644
--- a/include/perfetto/profiling/parse_smaps.h
+++ b/include/perfetto/profiling/parse_smaps.h
@@ -21,14 +21,13 @@
#ifndef INCLUDE_PERFETTO_PROFILING_PARSE_SMAPS_H_
#define INCLUDE_PERFETTO_PROFILING_PARSE_SMAPS_H_
-#include <string>
-
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include <inttypes.h>
+#include <cinttypes>
+#include <string>
namespace perfetto {
namespace profiling {
diff --git a/include/perfetto/protozero/proto_utils.h b/include/perfetto/protozero/proto_utils.h
index 6b195cb..fe64da3 100644
--- a/include/perfetto/protozero/proto_utils.h
+++ b/include/perfetto/protozero/proto_utils.h
@@ -17,9 +17,9 @@
#ifndef INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_
#define INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_
-#include <inttypes.h>
#include <stddef.h>
+#include <cinttypes>
#include <type_traits>
#include "perfetto/base/logging.h"
diff --git a/include/perfetto/trace_processor/basic_types.h b/include/perfetto/trace_processor/basic_types.h
index 2b38b6d..5b459d0 100644
--- a/include/perfetto/trace_processor/basic_types.h
+++ b/include/perfetto/trace_processor/basic_types.h
@@ -23,6 +23,7 @@
#include <stdint.h>
#include <functional>
#include <string>
+#include <vector>
#include "perfetto/base/export.h"
#include "perfetto/base/logging.h"
@@ -34,12 +35,17 @@
// simpler (e.g. use arrays instead of vectors).
constexpr size_t kMaxCpus = 128;
+// All metrics protos are in this directory. When loading metric extensions, the
+// protos are mounted onto a virtual path inside this directory.
+constexpr char kMetricProtoRoot[] = "protos/perfetto/metrics/";
+
// Enum which encodes how trace processor should try to sort the ingested data.
+// Note that these options are only applicable to proto traces; other trace
+// types (e.g. JSON, Fuchsia) use full sorts.
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.
+ // trace processor reads information from the trace to make the best decision.
//
// The exact heuristics are implementation details but will ensure that all
// relevant tables are sorted by timestamp.
@@ -53,14 +59,19 @@
// 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.
+ // This option is deprecated in v18; trace processor will ignore it and
+ // use |kDefaultHeuristics|.
//
- // If a |flush_period_ms| is not specified in the TraceConfig, this mode will
- // act the same as |SortingMode::kDefaultHeuristics|.
+ // Rationale for deprecation:
+ // The new windowed sorting logic in trace processor uses a combination of
+ // flush and buffer-read lifecycle events inside the trace instead of
+ // using time-periods from the config.
+ //
+ // Recommended migration:
+ // Users of this option should switch to using |kDefaultHeuristics| which
+ // will act very similarly to the pre-v20 behaviour of this option.
+ //
+ // This option is scheduled to be removed in v21.
kForceFlushPeriodWindowedSort = 2
};
@@ -106,6 +117,10 @@
// the trace before that event. See the ennu documenetation for more details.
DropFtraceDataBefore drop_ftrace_data_before =
DropFtraceDataBefore::kTracingStarted;
+
+ // Any built-in metric proto or sql files matching these paths are skipped
+ // during trace processor metric initialization.
+ std::vector<std::string> skip_builtin_metric_paths;
};
// Represents a dynamically typed value returned by SQL.
diff --git a/include/perfetto/trace_processor/trace_processor.h b/include/perfetto/trace_processor/trace_processor.h
index c949695..77a7889 100644
--- a/include/perfetto/trace_processor/trace_processor.h
+++ b/include/perfetto/trace_processor/trace_processor.h
@@ -57,6 +57,13 @@
// proto builder functions when computing metrics.
virtual util::Status ExtendMetricsProto(const uint8_t* data, size_t size) = 0;
+ // Behaves exactly as ExtendMetricsProto, except any FileDescriptor with
+ // filename matching a prefix in |skip_prefixes| is skipped.
+ virtual util::Status ExtendMetricsProto(
+ const uint8_t* data,
+ size_t size,
+ const std::vector<std::string>& skip_prefixes) = 0;
+
// Computes the given metrics on the loded portion of the trace. If
// successful, the output argument |metrics_proto| will be filled with the
// proto-encoded bytes for the message TraceMetrics in
diff --git a/include/perfetto/tracing/data_source.h b/include/perfetto/tracing/data_source.h
index c4c6681..6b2a81a 100644
--- a/include/perfetto/tracing/data_source.h
+++ b/include/perfetto/tracing/data_source.h
@@ -536,22 +536,7 @@
#define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(...) \
template <> \
PERFETTO_COMPONENT_EXPORT perfetto::internal::DataSourceStaticState \
- perfetto::DataSource<__VA_ARGS__>::static_state_; \
- template <> \
- PERFETTO_COMPONENT_EXPORT PERFETTO_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
+ perfetto::DataSource<__VA_ARGS__>::static_state_
// 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.
@@ -563,10 +548,6 @@
#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::DataSource<__VA_ARGS__>::tls_state_ = nullptr
+ perfetto::DataSource<__VA_ARGS__>::static_state_ {}
#endif // INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
diff --git a/include/perfetto/tracing/internal/track_event_macros.h b/include/perfetto/tracing/internal/track_event_macros.h
index 0c7ffb7..c82134d 100644
--- a/include/perfetto/tracing/internal/track_event_macros.h
+++ b/include/perfetto/tracing/internal/track_event_macros.h
@@ -59,11 +59,15 @@
/* variable), we need two separate copies of the registry with different */ \
/* storage specifiers. */ \
/**/ \
+ /* Note that because of a Clang/Windows bug, the constexpr category */ \
+ /* registry isn't given the enabled/disabled state array. All access */ \
+ /* to the category states should therefore be done through the */ \
+ /* non-constexpr registry. See */ \
+ /* https://bugs.llvm.org/show_bug.cgi?id=51558 */ \
+ /**/ \
/* TODO(skyostil): Unify these using a C++17 inline constexpr variable. */ \
constexpr ::perfetto::internal::TrackEventCategoryRegistry \
- kConstExprCategoryRegistry(kCategoryCount, \
- &kCategories[0], \
- &g_category_state_storage[0]); \
+ kConstExprCategoryRegistry(kCategoryCount, &kCategories[0], nullptr); \
PERFETTO_COMPONENT_EXPORT extern const ::perfetto::internal:: \
TrackEventCategoryRegistry kCategoryRegistry; \
static_assert(kConstExprCategoryRegistry.ValidateCategories(), \
@@ -83,10 +87,9 @@
} // namespace internal
// Defines the TrackEvent data source for the current track event namespace.
-#define PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE() \
- struct PERFETTO_COMPONENT_EXPORT TrackEvent \
- : public ::perfetto::internal::TrackEventDataSource< \
- TrackEvent, &internal::kCategoryRegistry> {}
+#define PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE() \
+ struct TrackEvent : public ::perfetto::internal::TrackEventDataSource< \
+ TrackEvent, &internal::kCategoryRegistry> {}
// At compile time, turns a category name represented by a static string into an
// index into the current category registry. A build error will be generated if
@@ -158,4 +161,22 @@
: ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::IsCategoryEnabled( \
PERFETTO_GET_CATEGORY_INDEX(category)))
+// Emits an empty trace packet into the trace to ensure that the service can
+// safely read the last event from the trace buffer. This can be used to
+// periodically "flush" the last event on threads that don't support explicit
+// flushing of the shared memory buffer chunk when the tracing session stops
+// (e.g. thread pool workers in Chromium).
+//
+// This workaround is only required because the tracing service cannot safely
+// read the last trace packet from an incomplete SMB chunk (crbug.com/1021571
+// and b/162206162) when scraping the SMB. Adding an empty trace packet ensures
+// that all prior events can be scraped by the service.
+#define PERFETTO_INTERNAL_ADD_EMPTY_EVENT() \
+ do { \
+ ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::Trace( \
+ [](::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::TraceContext ctx) { \
+ ctx.NewTracePacket(); \
+ }); \
+ } while (false)
+
#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_MACROS_H_
diff --git a/include/perfetto/tracing/platform.h b/include/perfetto/tracing/platform.h
index ecd74d9..7a065cf 100644
--- a/include/perfetto/tracing/platform.h
+++ b/include/perfetto/tracing/platform.h
@@ -70,7 +70,12 @@
// Creates a sequenced task runner. The easiest implementation is to create
// a new thread (e.g. use base::ThreadTaskRunner) but this can also be
// implemented in some more clever way (e.g. using chromiums's scheduler).
- struct CreateTaskRunnerArgs {};
+ struct CreateTaskRunnerArgs {
+ // Optional. Sets the name to the newly created task runner. In the default
+ // PosixPlatform implementation this causes a pthread_setname_np(). This is
+ // only for ease of debugging, it does not affect the tracing behavior.
+ std::string name_for_debugging;
+ };
virtual std::unique_ptr<base::TaskRunner> CreateTaskRunner(
const CreateTaskRunnerArgs&) = 0;
diff --git a/include/perfetto/tracing/track.h b/include/perfetto/tracing/track.h
index 0ff225d..8c22aad 100644
--- a/include/perfetto/tracing/track.h
+++ b/include/perfetto/tracing/track.h
@@ -104,7 +104,8 @@
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.
+ // processes. If you hit this check but are providing no |parent| track,
+ // verify that Tracing::Initialize() was called for the current process.
PERFETTO_DCHECK(parent.uuid != Track().uuid);
return Track(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr)),
diff --git a/include/perfetto/tracing/track_event_legacy.h b/include/perfetto/tracing/track_event_legacy.h
index cd86510..197d559 100644
--- a/include/perfetto/tracing/track_event_legacy.h
+++ b/include/perfetto/tracing/track_event_legacy.h
@@ -158,8 +158,7 @@
static constexpr char TRACE_EVENT_SCOPE_NAME_PROCESS = 'p';
static constexpr char TRACE_EVENT_SCOPE_NAME_THREAD = 't';
-static constexpr auto TRACE_EVENT_API_CURRENT_THREAD_ID =
- perfetto::legacy::kCurrentThreadId;
+#define TRACE_EVENT_API_CURRENT_THREAD_ID ::perfetto::legacy::kCurrentThreadId
#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
@@ -451,46 +450,46 @@
// 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 PERFETTO_INTERNAL_LEGACY_EVENT(phase, category, name, flags, \
+ thread_id, ...) \
+ [&]() { \
+ using ::perfetto::internal::TrackEventInternal; \
+ /* 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, TrackEventInternal::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, ...) \
@@ -879,6 +878,16 @@
TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
arg1_name, arg1_val)
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP_AND_FLAGS0( \
+ category_group, name, id, timestamp, flags) \
+ 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, flags)
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(category_group, name, \
+ id, timestamp) \
+ 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)
#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP2(category_group, name, id, \
timestamp, arg1_name, \
arg1_val, arg2_name, arg2_val) \
@@ -1004,6 +1013,10 @@
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_FLAGS0(category_group, name, id, \
+ flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \
+ category_group, name, id, flags)
#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( \
@@ -1026,6 +1039,10 @@
INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_FLAGS0(category_group, name, id, \
+ flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \
+ category_group, name, id, flags)
// Async instant events.
#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT0(category_group, name, id) \
@@ -1072,6 +1089,18 @@
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)
+#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)
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP_AND_FLAGS0( \
+ category_group, name, id, timestamp, flags) \
+ 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, flags)
#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT_WITH_TIMESTAMP0( \
category_group, name, id, timestamp) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
@@ -1081,6 +1110,16 @@
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \
category_group, name, id, \
TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN1(category_group, name, id, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN2( \
+ category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val)
#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END0(category_group, name, id) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \
category_group, name, id, \
@@ -1090,6 +1129,12 @@
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_COPY)
+#define TRACE_EVENT_COPY_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_COPY, \
+ arg1_name, arg1_val)
#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( \
category_group, name, id, timestamp) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
@@ -1212,7 +1257,7 @@
"Enabled flag pointers are not supported for dynamic trace " \
"categories."); \
}, \
- PERFETTO_TRACK_EVENT_NAMESPACE::internal::kConstExprCategoryRegistry \
+ PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry \
.GetCategoryState( \
::PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry \
.Find(category, /*is_dynamic=*/false)))
@@ -1220,7 +1265,7 @@
// 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 \
+ ::PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry \
.GetCategory( \
category_enabled_ptr - \
reinterpret_cast<const uint8_t*>( \
diff --git a/infra/ci/Makefile b/infra/ci/Makefile
index d4a3e16..09c57a0 100644
--- a/infra/ci/Makefile
+++ b/infra/ci/Makefile
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-include $(shell python config.py makefile)
+include $(shell python3 config.py makefile)
override COMMON_DEPS := Makefile *.py
override GCE_LOCAL_STARTUP_SCRIPT := worker/gce-startup-script.sh
@@ -142,7 +142,7 @@
.PHONY: cli
cli:
GOOGLE_APPLICATION_CREDENTIALS=test-credentials.json \
- python -i -c 'from common_utils import *; from config import *; \
+ python3 -i -c 'from common_utils import *; from config import *; \
SCOPES += ["https://www.googleapis.com/auth/firebase.database", \
"https://www.googleapis.com/auth/userinfo.email", \
"https://www.googleapis.com/auth/datastore"]'
diff --git a/infra/ci/sandbox/Dockerfile b/infra/ci/sandbox/Dockerfile
index 6f14c90..79da8d4 100644
--- a/infra/ci/sandbox/Dockerfile
+++ b/infra/ci/sandbox/Dockerfile
@@ -45,6 +45,20 @@
rm bazel-*-installer-linux-x86_64.sh; \
bazel version;
+# Chrome/puppeteer deps.
+RUN set -ex; \
+ export DEBIAN_FRONTEND=noninteractive; \
+ apt-get update; \
+ apt-get -y install gconf-service libasound2 libatk1.0-0 libc6 libcairo2 \
+ libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 \
+ libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \
+ libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 \
+ libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 \
+ libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 \
+ libxtst6 ca-certificates libappindicator1 libnss3 lsb-release \
+ xdg-utils fonts-liberation fonts-ipafont-gothic fonts-wqy-zenhei \
+ fonts-thai-tlwg fonts-kacst fonts-freefont-ttf
+
COPY testrunner.sh /ci/testrunner.sh
COPY init.sh /ci/init.sh
RUN chmod -R a+rx /ci/
diff --git a/infra/ci/worker/run_job.py b/infra/ci/worker/run_job.py
index 4706120..e5353c9 100755
--- a/infra/ci/worker/run_job.py
+++ b/infra/ci/worker/run_job.py
@@ -19,12 +19,10 @@
import fcntl
import logging
-import json
import os
import queue
import signal
import socket
-import shutil
import subprocess
import sys
import threading
@@ -45,10 +43,18 @@
res = ''
while True:
try:
- buf = os.read(fd.fileno(), 1024)
+ buf = os.read(fd.fileno(), 8192)
if not buf:
break
- res += buf.decode()
+ # There are two reasons for the errors='ignore' here:
+ # 1: By reading the pipe in chunks of N bytes, we can end up truncating
+ # a valid multi-byte character and cause an "unexpected end of data".
+ # This means that we will skip valid unicode chars if they happen to
+ # span across two read() chunks.
+ # 2: The job output might just emit some invalid unicode in stdout. We
+ # don't want to crash when that happens.
+ # See b/194053229 for more context.
+ res += buf.decode('utf-8', errors='ignore')
except OSError:
break
return res
diff --git a/infra/config/recipes.cfg b/infra/config/recipes.cfg
index 5743902..0b9c6c6 100644
--- a/infra/config/recipes.cfg
+++ b/infra/config/recipes.cfg
@@ -5,6 +5,11 @@
"branch": "refs/heads/master",
"revision": "2030661a4ff2a6b64b0651f2c44aabed8c71223f",
"url": "https://chromium.googlesource.com/infra/luci/recipes-py"
+ },
+ "depot_tools": {
+ "branch": "refs/heads/main",
+ "revision": "5345b34aaf50107d0a07146b9319ef19203f65a0",
+ "url": "https://chromium.googlesource.com/chromium/tools/depot_tools.git"
}
},
"project_id": "perfetto",
diff --git a/infra/luci/README.recipes.md b/infra/luci/README.recipes.md
index 8d601e9..0965828 100644
--- a/infra/luci/README.recipes.md
+++ b/infra/luci/README.recipes.md
@@ -2,22 +2,115 @@
# Repo documentation for [perfetto]()
## Table of Contents
+**[Recipe Modules](#Recipe-Modules)**
+ * [macos_sdk](#recipe_modules-macos_sdk) — The `macos_sdk` module provides safe functions to access a semi-hermetic XCode installation.
+ * [windows_sdk](#recipe_modules-windows_sdk)
+
**[Recipes](#Recipes)**
+ * [macos_sdk:examples/full](#recipes-macos_sdk_examples_full)
* [perfetto](#recipes-perfetto) — Recipe for building Perfetto.
+ * [windows_sdk:examples/full](#recipes-windows_sdk_examples_full)
+## Recipe Modules
+
+### *recipe_modules* / [macos\_sdk](/infra/luci/recipe_modules/macos_sdk)
+
+[DEPS](/infra/luci/recipe_modules/macos_sdk/__init__.py#15): [recipe\_engine/cipd][recipe_engine/recipe_modules/cipd], [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/json][recipe_engine/recipe_modules/json], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/platform][recipe_engine/recipe_modules/platform], [recipe\_engine/step][recipe_engine/recipe_modules/step]
+
+The `macos_sdk` module provides safe functions to access a semi-hermetic
+XCode installation.
+
+Available only to Google-run bots.
+
+#### **class [MacOSSDKApi](/infra/luci/recipe_modules/macos_sdk/api.py#24)([RecipeApi][recipe_engine/wkt/RecipeApi]):**
+
+API for using OS X SDK distributed via CIPD.
+
+  **@contextmanager**<br>— **def [\_\_call\_\_](/infra/luci/recipe_modules/macos_sdk/api.py#40)(self):**
+
+Sets up the XCode SDK environment.
+
+This call is a no-op on non-Mac platforms.
+
+This will deploy the helper tool and the XCode.app bundle at
+`[START_DIR]/cache/macos_sdk`.
+
+To avoid machines rebuilding these on every run, set up a named cache in
+your cr-buildbucket.cfg file like:
+
+ caches: {
+ # Cache for mac_toolchain tool and XCode.app
+ name: "macos_sdk"
+ path: "macos_sdk"
+ }
+
+If you have builders which e.g. use a non-current SDK, you can give them
+a uniqely named cache:
+
+ caches: {
+ # Cache for N-1 version mac_toolchain tool and XCode.app
+ name: "macos_sdk_old"
+ path: "macos_sdk"
+ }
+
+Usage:
+ with api.macos_sdk():
+ # sdk with mac build bits
+
+Raises:
+ StepFailure or InfraFailure.
+
+  **@property**<br>— **def [sdk\_dir](/infra/luci/recipe_modules/macos_sdk/api.py#35)(self):**
+### *recipe_modules* / [windows\_sdk](/infra/luci/recipe_modules/windows_sdk)
+
+[DEPS](/infra/luci/recipe_modules/windows_sdk/__init__.py#15): [recipe\_engine/cipd][recipe_engine/recipe_modules/cipd], [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/json][recipe_engine/recipe_modules/json], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/platform][recipe_engine/recipe_modules/platform], [recipe\_engine/step][recipe_engine/recipe_modules/step]
+
+#### **class [WindowsSDKApi](/infra/luci/recipe_modules/windows_sdk/api.py#20)([RecipeApi][recipe_engine/wkt/RecipeApi]):**
+
+API for using Windows SDK distributed via CIPD.
+
+  **@contextmanager**<br>— **def [\_\_call\_\_](/infra/luci/recipe_modules/windows_sdk/api.py#29)(self):**
+
+Setups the Windows SDK environment.
+
+This call is a no-op on non-Windows platforms.
+
+Raises:
+ StepFailure or InfraFailure.
## Recipes
+### *recipes* / [macos\_sdk:examples/full](/infra/luci/recipe_modules/macos_sdk/examples/full.py)
+
+[DEPS](/infra/luci/recipe_modules/macos_sdk/examples/full.py#15): [macos\_sdk](#recipe_modules-macos_sdk), [recipe\_engine/platform][recipe_engine/recipe_modules/platform], [recipe\_engine/properties][recipe_engine/recipe_modules/properties], [recipe\_engine/step][recipe_engine/recipe_modules/step]
+
+— **def [RunSteps](/infra/luci/recipe_modules/macos_sdk/examples/full.py#23)(api):**
### *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]
+[DEPS](/infra/luci/recipes/perfetto.py#18): [depot\_tools/gsutil][depot_tools/recipe_modules/gsutil], [macos\_sdk](#recipe_modules-macos_sdk), [windows\_sdk](#recipe_modules-windows_sdk), [recipe\_engine/buildbucket][recipe_engine/recipe_modules/buildbucket], [recipe\_engine/cipd][recipe_engine/recipe_modules/cipd], [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/raw\_io][recipe_engine/recipe_modules/raw_io], [recipe\_engine/step][recipe_engine/recipe_modules/step]
Recipe for building Perfetto.
-— **def [RunSteps](/infra/luci/recipes/perfetto.py#39)(api, repository):**
+— **def [BuildForPlatform](/infra/luci/recipes/perfetto.py#138)(api, ctx, platform):**
+— **def [GnArgs](/infra/luci/recipes/perfetto.py#81)(platform):**
+
+— **def [RunSteps](/infra/luci/recipes/perfetto.py#164)(api, repository):**
+
+— **def [UploadArtifact](/infra/luci/recipes/perfetto.py#90)(api, ctx, platform, out_dir, artifact):**
+### *recipes* / [windows\_sdk:examples/full](/infra/luci/recipe_modules/windows_sdk/examples/full.py)
+
+[DEPS](/infra/luci/recipe_modules/windows_sdk/examples/full.py#15): [windows\_sdk](#recipe_modules-windows_sdk), [recipe\_engine/platform][recipe_engine/recipe_modules/platform], [recipe\_engine/properties][recipe_engine/recipe_modules/properties], [recipe\_engine/step][recipe_engine/recipe_modules/step]
+
+— **def [RunSteps](/infra/luci/recipe_modules/windows_sdk/examples/full.py#23)(api):**
+
+[depot_tools/recipe_modules/gsutil]: https://chromium.googlesource.com/chromium/tools/depot_tools.git/+/5345b34aaf50107d0a07146b9319ef19203f65a0/recipes/README.recipes.md#recipe_modules-gsutil
[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/cipd]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-cipd
[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/json]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-json
[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/raw_io]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-raw_io
[recipe_engine/recipe_modules/step]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-step
+[recipe_engine/wkt/RecipeApi]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/recipe_engine/recipe_api.py#856
diff --git a/infra/luci/generated/cr-buildbucket.cfg b/infra/luci/generated/cr-buildbucket.cfg
new file mode 100644
index 0000000..18a7c5a
--- /dev/null
+++ b/infra/luci/generated/cr-buildbucket.cfg
@@ -0,0 +1,94 @@
+# Auto-generated by lucicfg.
+# Do not modify manually.
+#
+# For the schema of this file, see BuildbucketCfg message:
+# https://luci-config.appspot.com/schemas/projects:buildbucket.cfg
+
+buckets {
+ name: "official"
+ acls {
+ group: "all"
+ }
+ acls {
+ role: SCHEDULER
+ group: "mdb/chrome-troopers"
+ }
+ acls {
+ role: SCHEDULER
+ group: "mdb/perfetto-cloud-infra"
+ }
+ swarming {
+ builders {
+ name: "perfetto-official-builder-android"
+ swarming_host: "chrome-swarming.appspot.com"
+ dimensions: "cpu:x86-64"
+ dimensions: "os:Linux"
+ dimensions: "pool:luci.perfetto.official"
+ exe {
+ cipd_package: "infra/recipe_bundles/android.googlesource.com/platform/external/perfetto"
+ cipd_version: "refs/heads/master"
+ cmd: "luciexe"
+ }
+ properties: "{\"recipe\":\"perfetto\"}"
+ service_account: "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
+ experiments {
+ key: "luci.use_realms"
+ value: 100
+ }
+ }
+ builders {
+ name: "perfetto-official-builder-linux"
+ swarming_host: "chrome-swarming.appspot.com"
+ dimensions: "cpu:x86-64"
+ dimensions: "os:Linux"
+ dimensions: "pool:luci.perfetto.official"
+ exe {
+ cipd_package: "infra/recipe_bundles/android.googlesource.com/platform/external/perfetto"
+ cipd_version: "refs/heads/master"
+ cmd: "luciexe"
+ }
+ properties: "{\"recipe\":\"perfetto\"}"
+ service_account: "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
+ experiments {
+ key: "luci.use_realms"
+ value: 100
+ }
+ }
+ builders {
+ name: "perfetto-official-builder-mac"
+ swarming_host: "chrome-swarming.appspot.com"
+ dimensions: "cpu:x86-64"
+ dimensions: "os:Mac"
+ dimensions: "pool:luci.perfetto.official"
+ exe {
+ cipd_package: "infra/recipe_bundles/android.googlesource.com/platform/external/perfetto"
+ cipd_version: "refs/heads/master"
+ cmd: "luciexe"
+ }
+ properties: "{\"recipe\":\"perfetto\"}"
+ service_account: "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
+ experiments {
+ key: "luci.use_realms"
+ value: 100
+ }
+ }
+ builders {
+ name: "perfetto-official-builder-windows"
+ swarming_host: "chrome-swarming.appspot.com"
+ dimensions: "cpu:x86-64"
+ dimensions: "os:Windows"
+ dimensions: "pool:luci.perfetto.official"
+ exe {
+ cipd_package: "infra/recipe_bundles/android.googlesource.com/platform/external/perfetto"
+ cipd_version: "refs/heads/master"
+ cmd: "luciexe"
+ }
+ properties: "{\"recipe\":\"perfetto\"}"
+ service_account: "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
+ experiments {
+ key: "luci.use_realms"
+ value: 100
+ }
+ }
+ }
+}
diff --git a/infra/luci/generated/luci-logdog.cfg b/infra/luci/generated/luci-logdog.cfg
new file mode 100644
index 0000000..adc75be
--- /dev/null
+++ b/infra/luci/generated/luci-logdog.cfg
@@ -0,0 +1,9 @@
+# Auto-generated by lucicfg.
+# Do not modify manually.
+#
+# For the schema of this file, see ProjectConfig message:
+# https://luci-config.appspot.com/schemas/projects:luci-logdog.cfg
+
+reader_auth_groups: "all"
+writer_auth_groups: "luci-logdog-chromium-writers"
+archive_gs_bucket: "chromium-luci-logdog"
diff --git a/infra/luci/generated/luci-scheduler.cfg b/infra/luci/generated/luci-scheduler.cfg
new file mode 100644
index 0000000..89ae71b
--- /dev/null
+++ b/infra/luci/generated/luci-scheduler.cfg
@@ -0,0 +1,73 @@
+# Auto-generated by lucicfg.
+# Do not modify manually.
+#
+# For the schema of this file, see ProjectConfig message:
+# https://luci-config.appspot.com/schemas/projects:luci-scheduler.cfg
+
+job {
+ id: "perfetto-official-builder-android"
+ realm: "official"
+ acl_sets: "official"
+ buildbucket {
+ server: "cr-buildbucket.appspot.com"
+ bucket: "luci.perfetto.official"
+ builder: "perfetto-official-builder-android"
+ }
+}
+job {
+ id: "perfetto-official-builder-linux"
+ realm: "official"
+ acl_sets: "official"
+ buildbucket {
+ server: "cr-buildbucket.appspot.com"
+ bucket: "luci.perfetto.official"
+ builder: "perfetto-official-builder-linux"
+ }
+}
+job {
+ id: "perfetto-official-builder-mac"
+ realm: "official"
+ acl_sets: "official"
+ buildbucket {
+ server: "cr-buildbucket.appspot.com"
+ bucket: "luci.perfetto.official"
+ builder: "perfetto-official-builder-mac"
+ }
+}
+job {
+ id: "perfetto-official-builder-windows"
+ realm: "official"
+ acl_sets: "official"
+ buildbucket {
+ server: "cr-buildbucket.appspot.com"
+ bucket: "luci.perfetto.official"
+ builder: "perfetto-official-builder-windows"
+ }
+}
+trigger {
+ id: "perfetto-gitiles-trigger"
+ realm: "official"
+ acl_sets: "official"
+ triggers: "perfetto-official-builder-android"
+ triggers: "perfetto-official-builder-linux"
+ triggers: "perfetto-official-builder-mac"
+ triggers: "perfetto-official-builder-windows"
+ gitiles {
+ repo: "https://android.googlesource.com/platform/external/perfetto"
+ refs: "regexp:refs/tags/v.+"
+ }
+}
+acl_sets {
+ name: "official"
+ acls {
+ role: OWNER
+ granted_to: "group:mdb/perfetto-cloud-infra"
+ }
+ acls {
+ granted_to: "group:all"
+ }
+ acls {
+ role: TRIGGERER
+ granted_to: "group:mdb/chrome-troopers"
+ }
+}
diff --git a/infra/luci/generated/project.cfg b/infra/luci/generated/project.cfg
new file mode 100644
index 0000000..fbf2a59
--- /dev/null
+++ b/infra/luci/generated/project.cfg
@@ -0,0 +1,8 @@
+# Auto-generated by lucicfg.
+# Do not modify manually.
+#
+# For the schema of this file, see ProjectCfg message:
+# https://luci-config.appspot.com/schemas/projects:project.cfg
+
+name: "perfetto"
+access: "group:all"
diff --git a/infra/luci/generated/realms.cfg b/infra/luci/generated/realms.cfg
new file mode 100644
index 0000000..522d5c6
--- /dev/null
+++ b/infra/luci/generated/realms.cfg
@@ -0,0 +1,52 @@
+# Auto-generated by lucicfg.
+# Do not modify manually.
+#
+# For the schema of this file, see RealmsCfg message:
+# https://luci-config.appspot.com/schemas/projects:realms.cfg
+
+realms {
+ name: "@root"
+ bindings {
+ role: "role/buildbucket.reader"
+ principals: "group:all"
+ }
+ bindings {
+ role: "role/configs.reader"
+ principals: "group:all"
+ }
+ bindings {
+ role: "role/logdog.reader"
+ principals: "group:all"
+ }
+ bindings {
+ role: "role/logdog.writer"
+ principals: "group:luci-logdog-chromium-writers"
+ }
+ bindings {
+ role: "role/scheduler.owner"
+ principals: "group:mdb/perfetto-cloud-infra"
+ }
+ bindings {
+ role: "role/scheduler.reader"
+ principals: "group:all"
+ }
+}
+realms {
+ name: "official"
+ bindings {
+ role: "role/buildbucket.builderServiceAccount"
+ principals: "user:perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
+ }
+ bindings {
+ role: "role/buildbucket.triggerer"
+ principals: "group:mdb/chrome-troopers"
+ principals: "group:mdb/perfetto-cloud-infra"
+ }
+ bindings {
+ role: "role/scheduler.triggerer"
+ principals: "group:mdb/chrome-troopers"
+ }
+}
+realms {
+ name: "pools/official"
+}
diff --git a/infra/luci/main.star b/infra/luci/main.star
new file mode 100755
index 0000000..4119e2d
--- /dev/null
+++ b/infra/luci/main.star
@@ -0,0 +1,106 @@
+#!/usr/bin/env lucicfg
+# 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.
+
+lucicfg.check_version("1.23.3", "Please update depot_tools")
+
+# Enable LUCI Realms support and launch all builds in realms-aware mode.
+lucicfg.enable_experiment("crbug.com/1085650")
+luci.builder.defaults.experiments.set({"luci.use_realms": 100})
+
+# Enable bbagent.
+luci.recipe.defaults.use_bbagent.set(True)
+
+lucicfg.config(
+ config_dir = "generated",
+ fail_on_warnings = True,
+)
+
+luci.project(
+ name = "perfetto",
+ buildbucket = "cr-buildbucket.appspot.com",
+ logdog = "luci-logdog",
+ milo = "luci-milo",
+ scheduler = "luci-scheduler",
+ swarming = "chrome-swarming.appspot.com",
+ acls = [
+ acl.entry(
+ [
+ acl.BUILDBUCKET_READER,
+ acl.LOGDOG_READER,
+ acl.PROJECT_CONFIGS_READER,
+ acl.SCHEDULER_READER,
+ ],
+ groups = ["all"],
+ ),
+ acl.entry(roles = acl.SCHEDULER_OWNER, groups = "mdb/perfetto-cloud-infra"),
+ acl.entry([acl.LOGDOG_WRITER], groups = ["luci-logdog-chromium-writers"]),
+ ],
+)
+
+# Use the default Chromium logdog instance as:
+# a) we expect our logs to be very minimal
+# b) we are open source so there's nothing special in our logs.
+luci.logdog(
+ gs_bucket = "chromium-luci-logdog",
+)
+
+# Create a realm for the official pool.
+# Used by LUCI infra (Googlers: see pools.cfg) to enforce ACLs.
+luci.realm(name = "pools/official")
+
+# Bucket used by all official builders.
+luci.bucket(
+ name = "official",
+ acls = [
+ acl.entry(
+ roles = [acl.BUILDBUCKET_TRIGGERER],
+ groups = ["mdb/perfetto-cloud-infra"],
+ ),
+ acl.entry(
+ roles = [acl.SCHEDULER_TRIGGERER, acl.BUILDBUCKET_TRIGGERER],
+ groups = ["mdb/chrome-troopers"],
+ ),
+ ],
+)
+
+def official_builder(name, os):
+ luci.builder(
+ name = name,
+ bucket = "official",
+ executable = luci.recipe(
+ name = "perfetto",
+ cipd_package = "infra/recipe_bundles/android.googlesource.com/platform/external/perfetto",
+ cipd_version = "refs/heads/master",
+ ),
+ dimensions = {
+ "pool": "luci.perfetto.official",
+ "os": os,
+ "cpu": "x86-64",
+ },
+ service_account = "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com",
+ triggered_by = [
+ luci.gitiles_poller(
+ name = "perfetto-gitiles-trigger",
+ bucket = "official",
+ repo = "https://android.googlesource.com/platform/external/perfetto",
+ refs = ["refs/tags/v.+"],
+ ),
+ ],
+ )
+
+official_builder("perfetto-official-builder-linux", "Linux")
+official_builder("perfetto-official-builder-mac", "Mac")
+official_builder("perfetto-official-builder-windows", "Windows")
+official_builder("perfetto-official-builder-android", "Linux")
diff --git a/infra/luci/recipe_modules/macos_sdk/__init__.py b/infra/luci/recipe_modules/macos_sdk/__init__.py
new file mode 100644
index 0000000..0bd7a5d
--- /dev/null
+++ b/infra/luci/recipe_modules/macos_sdk/__init__.py
@@ -0,0 +1,54 @@
+# 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.
+
+DEPS = [
+ 'recipe_engine/cipd',
+ 'recipe_engine/context',
+ 'recipe_engine/json',
+ 'recipe_engine/path',
+ 'recipe_engine/platform',
+ 'recipe_engine/step',
+]
+
+from recipe_engine.recipe_api import Property
+from recipe_engine.config import ConfigGroup, Single
+
+PROPERTIES = {
+ '$perfetto/macos_sdk':
+ Property(
+ help='Properties specifically for the macos_sdk module.',
+ param_name='sdk_properties',
+ kind=ConfigGroup( # pylint: disable=line-too-long
+ # XCode build version number. Internally maps to an XCode build id like
+ # '9c40b'. See
+ #
+ # https://chrome-infra-packages.appspot.com/p/infra_internal/ios/xcode/mac/+/
+ #
+ # For an up to date list of the latest SDK builds.
+ sdk_version=Single(str),
+
+ # The CIPD toolchain tool package and version.
+ tool_pkg=Single(str),
+ tool_ver=Single(str),
+ ),
+ default={
+ 'sdk_version':
+ '12B5025f',
+ 'tool_package':
+ 'infra/tools/mac_toolchain/${platform}',
+ 'tool_version':
+ 'git_revision:e9b1fe29fe21a1cd36428c43ea2aba244bd31280',
+ },
+ )
+}
diff --git a/infra/luci/recipe_modules/macos_sdk/api.py b/infra/luci/recipe_modules/macos_sdk/api.py
new file mode 100644
index 0000000..06feafb
--- /dev/null
+++ b/infra/luci/recipe_modules/macos_sdk/api.py
@@ -0,0 +1,108 @@
+# 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 `macos_sdk` module provides safe functions to access a semi-hermetic
+XCode installation.
+
+Available only to Google-run bots."""
+
+from contextlib import contextmanager
+
+from recipe_engine import recipe_api
+
+
+class MacOSSDKApi(recipe_api.RecipeApi):
+ """API for using OS X SDK distributed via CIPD."""
+
+ def __init__(self, sdk_properties, *args, **kwargs):
+ super(MacOSSDKApi, self).__init__(*args, **kwargs)
+
+ self._sdk_dir = None
+ self._sdk_version = sdk_properties['sdk_version'].lower()
+ self._tool_package = sdk_properties['tool_package']
+ self._tool_version = sdk_properties['tool_version']
+
+ @property
+ def sdk_dir(self):
+ assert self._sdk_dir
+ return self._sdk_dir
+
+ @contextmanager
+ def __call__(self):
+ """Sets up the XCode SDK environment.
+
+ This call is a no-op on non-Mac platforms.
+
+ This will deploy the helper tool and the XCode.app bundle at
+ `[START_DIR]/cache/macos_sdk`.
+
+ To avoid machines rebuilding these on every run, set up a named cache in
+ your cr-buildbucket.cfg file like:
+
+ caches: {
+ # Cache for mac_toolchain tool and XCode.app
+ name: "macos_sdk"
+ path: "macos_sdk"
+ }
+
+ If you have builders which e.g. use a non-current SDK, you can give them
+ a uniqely named cache:
+
+ caches: {
+ # Cache for N-1 version mac_toolchain tool and XCode.app
+ name: "macos_sdk_old"
+ path: "macos_sdk"
+ }
+
+ Usage:
+ with api.macos_sdk():
+ # sdk with mac build bits
+
+ Raises:
+ StepFailure or InfraFailure.
+ """
+ if not self.m.platform.is_mac:
+ yield
+ return
+
+ try:
+ with self.m.context(infra_steps=True):
+ self._sdk_dir = self._ensure_sdk()
+ self.m.step('select XCode',
+ ['sudo', 'xcode-select', '--switch', self._sdk_dir])
+ yield
+ finally:
+ with self.m.context(infra_steps=True):
+ self.m.step('reset XCode', ['sudo', 'xcode-select', '--reset'])
+
+ def _ensure_sdk(self):
+ """Ensures the mac_toolchain tool and MacOS SDK packages are installed.
+
+ Returns Path to the installed sdk app bundle."""
+ cache_dir = self.m.path['cache'].join('macos_sdk')
+ pkgs = self.m.cipd.EnsureFile()
+ pkgs.add_package(self._tool_package, self._tool_version)
+ self.m.cipd.ensure(cache_dir, pkgs)
+
+ sdk_dir = cache_dir.join('XCode.app')
+ self.m.step('install xcode', [
+ cache_dir.join('mac_toolchain'),
+ 'install',
+ '-kind',
+ 'mac',
+ '-xcode-version',
+ self._sdk_version,
+ '-output-dir',
+ sdk_dir,
+ ])
+ return sdk_dir
diff --git a/infra/luci/recipe_modules/macos_sdk/examples/full.expected/linux.json b/infra/luci/recipe_modules/macos_sdk/examples/full.expected/linux.json
new file mode 100644
index 0000000..5b0f352
--- /dev/null
+++ b/infra/luci/recipe_modules/macos_sdk/examples/full.expected/linux.json
@@ -0,0 +1,21 @@
+[
+ {
+ "cmd": [
+ "gn",
+ "gen",
+ "out/Release"
+ ],
+ "name": "gn"
+ },
+ {
+ "cmd": [
+ "ninja",
+ "-C",
+ "out/Release"
+ ],
+ "name": "ninja"
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipe_modules/macos_sdk/examples/full.expected/mac.json b/infra/luci/recipe_modules/macos_sdk/examples/full.expected/mac.json
new file mode 100644
index 0000000..ab278fd
--- /dev/null
+++ b/infra/luci/recipe_modules/macos_sdk/examples/full.expected/mac.json
@@ -0,0 +1,83 @@
+[
+ {
+ "cmd": [
+ "cipd",
+ "ensure",
+ "-root",
+ "[CACHE]/macos_sdk",
+ "-ensure-file",
+ "infra/tools/mac_toolchain/${platform} git_revision:e9b1fe29fe21a1cd36428c43ea2aba244bd31280",
+ "-max-threads",
+ "0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "infra_step": true,
+ "name": "ensure_installed",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"resolved-instance_id-of-git_revision:e9b\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"infra/tools/mac_toolchain/resolved-platform\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "[CACHE]/macos_sdk/mac_toolchain",
+ "install",
+ "-kind",
+ "mac",
+ "-xcode-version",
+ "12b5025f",
+ "-output-dir",
+ "[CACHE]/macos_sdk/XCode.app"
+ ],
+ "infra_step": true,
+ "name": "install xcode"
+ },
+ {
+ "cmd": [
+ "sudo",
+ "xcode-select",
+ "--switch",
+ "[CACHE]/macos_sdk/XCode.app"
+ ],
+ "infra_step": true,
+ "name": "select XCode"
+ },
+ {
+ "cmd": [
+ "gn",
+ "gen",
+ "out/Release"
+ ],
+ "name": "gn"
+ },
+ {
+ "cmd": [
+ "ninja",
+ "-C",
+ "out/Release"
+ ],
+ "name": "ninja"
+ },
+ {
+ "cmd": [
+ "sudo",
+ "xcode-select",
+ "--reset"
+ ],
+ "infra_step": true,
+ "name": "reset XCode"
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipe_modules/macos_sdk/examples/full.expected/win.json b/infra/luci/recipe_modules/macos_sdk/examples/full.expected/win.json
new file mode 100644
index 0000000..5b0f352
--- /dev/null
+++ b/infra/luci/recipe_modules/macos_sdk/examples/full.expected/win.json
@@ -0,0 +1,21 @@
+[
+ {
+ "cmd": [
+ "gn",
+ "gen",
+ "out/Release"
+ ],
+ "name": "gn"
+ },
+ {
+ "cmd": [
+ "ninja",
+ "-C",
+ "out/Release"
+ ],
+ "name": "ninja"
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipe_modules/macos_sdk/examples/full.py b/infra/luci/recipe_modules/macos_sdk/examples/full.py
new file mode 100644
index 0000000..6d7ded3
--- /dev/null
+++ b/infra/luci/recipe_modules/macos_sdk/examples/full.py
@@ -0,0 +1,33 @@
+# 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.
+
+DEPS = [
+ 'macos_sdk',
+ 'recipe_engine/platform',
+ 'recipe_engine/properties',
+ 'recipe_engine/step',
+]
+
+
+def RunSteps(api):
+ with api.macos_sdk():
+ sdk_dir = api.macos_sdk.sdk_dir if api.platform.is_mac else None
+ api.step('gn', ['gn', 'gen', 'out/Release'])
+ api.step('ninja', ['ninja', '-C', 'out/Release'])
+
+
+def GenTests(api):
+ for platform in ('linux', 'mac', 'win'):
+ yield (api.test(platform) + api.platform.name(platform) +
+ api.properties.generic(buildername='test_builder'))
\ No newline at end of file
diff --git a/infra/luci/recipe_modules/windows_sdk/__init__.py b/infra/luci/recipe_modules/windows_sdk/__init__.py
new file mode 100644
index 0000000..f86fd54
--- /dev/null
+++ b/infra/luci/recipe_modules/windows_sdk/__init__.py
@@ -0,0 +1,41 @@
+# 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.
+
+DEPS = [
+ 'recipe_engine/cipd',
+ 'recipe_engine/context',
+ 'recipe_engine/json',
+ 'recipe_engine/path',
+ 'recipe_engine/platform',
+ 'recipe_engine/step',
+]
+
+from recipe_engine.recipe_api import Property
+from recipe_engine.config import ConfigGroup, Single
+
+PROPERTIES = {
+ '$perfetto/windows_sdk':
+ Property(
+ help='Properties specifically for the windows_sdk module.',
+ param_name='sdk_properties',
+ kind=ConfigGroup(
+ # The CIPD package and version.
+ sdk_package=Single(str),
+ sdk_version=Single(str)),
+ default={
+ 'sdk_package': 'chrome_internal/third_party/sdk/windows',
+ 'sdk_version': 'uploaded:2019-09-06'
+ },
+ )
+}
\ No newline at end of file
diff --git a/infra/luci/recipe_modules/windows_sdk/api.py b/infra/luci/recipe_modules/windows_sdk/api.py
new file mode 100644
index 0000000..921f37a
--- /dev/null
+++ b/infra/luci/recipe_modules/windows_sdk/api.py
@@ -0,0 +1,114 @@
+# 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 contextlib import contextmanager
+
+from recipe_engine import recipe_api
+
+
+class WindowsSDKApi(recipe_api.RecipeApi):
+ """API for using Windows SDK distributed via CIPD."""
+
+ def __init__(self, sdk_properties, *args, **kwargs):
+ super(WindowsSDKApi, self).__init__(*args, **kwargs)
+
+ self._sdk_package = sdk_properties['sdk_package']
+ self._sdk_version = sdk_properties['sdk_version']
+
+ @contextmanager
+ def __call__(self):
+ """Setups the Windows SDK environment.
+
+ This call is a no-op on non-Windows platforms.
+
+ Raises:
+ StepFailure or InfraFailure.
+ """
+ if not self.m.platform.is_win:
+ yield
+ return
+
+ with self.m.context(infra_steps=True):
+ sdk_dir = self._ensure_sdk()
+ with self.m.context(**self._sdk_env(sdk_dir)):
+ yield
+
+ def _ensure_sdk(self):
+ """Ensures the Windows SDK CIPD package is installed.
+
+ Returns the directory where the SDK package has been installed.
+
+ Args:
+ path (path): Path to a directory.
+ version (str): CIPD instance ID, tag or ref.
+ """
+ sdk_dir = self.m.path['cache'].join('windows_sdk')
+ pkgs = self.m.cipd.EnsureFile()
+ pkgs.add_package(self._sdk_package, self._sdk_version)
+ self.m.cipd.ensure(sdk_dir, pkgs)
+ return sdk_dir
+
+ def _sdk_env(self, sdk_dir):
+ """Constructs the environment for the SDK.
+
+ Returns environment and environment prefixes.
+
+ Args:
+ sdk_dir (path): Path to a directory containing the SDK.
+ """
+ env = {}
+ env_prefixes = {}
+
+ # Load .../win_sdk/bin/SetEnv.${arch}.json to extract the required
+ # environment. It contains a dict that looks like this:
+ # {
+ # "env": {
+ # "VAR": [["..", "..", "x"], ["..", "..", "y"]],
+ # ...
+ # }
+ # }
+ # All these environment variables need to be added to the environment
+ # for the compiler and linker to work.
+ filename = 'SetEnv.%s.json' % {32: 'x86', 64: 'x64'}[self.m.platform.bits]
+ step_result = self.m.json.read(
+ 'read %s' % filename,
+ sdk_dir.join('win_sdk', 'bin', filename),
+ step_test_data=lambda: self.m.json.test_api.output({
+ 'env': {
+ 'PATH': [['..', '..', 'win_sdk', 'bin', 'x64']],
+ 'VSINSTALLDIR': [['..', '..\\']],
+ },
+ }))
+ data = step_result.json.output.get('env')
+ for key in data:
+ # recipes' Path() does not like .., ., \, or /, so this is cumbersome.
+ # What we want to do is:
+ # [sdk_bin_dir.join(*e) for e in env[k]]
+ # Instead do that badly, and rely (but verify) on the fact that the paths
+ # are all specified relative to the root, but specified relative to
+ # win_sdk/bin (i.e. everything starts with "../../".)
+ results = []
+ for value in data[key]:
+ assert value[0] == '..' and (value[1] == '..' or value[1] == '..\\')
+ results.append('%s' % sdk_dir.join(*value[2:]))
+
+ # PATH is special-cased because we don't want to overwrite other things
+ # like C:\Windows\System32. Others are replacements because prepending
+ # doesn't necessarily makes sense, like VSINSTALLDIR.
+ if key.lower() == 'path':
+ env_prefixes[key] = results
+ else:
+ env[key] = ';'.join(results)
+
+ return {'env': env, 'env_prefixes': env_prefixes}
diff --git a/infra/luci/recipe_modules/windows_sdk/examples/full.expected/linux.json b/infra/luci/recipe_modules/windows_sdk/examples/full.expected/linux.json
new file mode 100644
index 0000000..5b0f352
--- /dev/null
+++ b/infra/luci/recipe_modules/windows_sdk/examples/full.expected/linux.json
@@ -0,0 +1,21 @@
+[
+ {
+ "cmd": [
+ "gn",
+ "gen",
+ "out/Release"
+ ],
+ "name": "gn"
+ },
+ {
+ "cmd": [
+ "ninja",
+ "-C",
+ "out/Release"
+ ],
+ "name": "ninja"
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipe_modules/windows_sdk/examples/full.expected/mac.json b/infra/luci/recipe_modules/windows_sdk/examples/full.expected/mac.json
new file mode 100644
index 0000000..5b0f352
--- /dev/null
+++ b/infra/luci/recipe_modules/windows_sdk/examples/full.expected/mac.json
@@ -0,0 +1,21 @@
+[
+ {
+ "cmd": [
+ "gn",
+ "gen",
+ "out/Release"
+ ],
+ "name": "gn"
+ },
+ {
+ "cmd": [
+ "ninja",
+ "-C",
+ "out/Release"
+ ],
+ "name": "ninja"
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipe_modules/windows_sdk/examples/full.expected/win.json b/infra/luci/recipe_modules/windows_sdk/examples/full.expected/win.json
new file mode 100644
index 0000000..b325275
--- /dev/null
+++ b/infra/luci/recipe_modules/windows_sdk/examples/full.expected/win.json
@@ -0,0 +1,98 @@
+[
+ {
+ "cmd": [
+ "cipd.bat",
+ "ensure",
+ "-root",
+ "[CACHE]\\windows_sdk",
+ "-ensure-file",
+ "chrome_internal/third_party/sdk/windows uploaded:2019-09-06",
+ "-max-threads",
+ "0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "infra_step": true,
+ "name": "ensure_installed",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"resolved-instance_id-of-uploaded:2019-09\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"chrome_internal/third_party/sdk/windows\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "\nimport shutil\nimport sys\nshutil.copy(sys.argv[1], sys.argv[2])\n",
+ "[CACHE]\\windows_sdk\\win_sdk\\bin\\SetEnv.x64.json",
+ "/path/to/tmp/json"
+ ],
+ "name": "read SetEnv.x64.json",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"env\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"PATH\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ [@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"..\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"..\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"win_sdk\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"bin\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ ], @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"VSINSTALLDIR\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ [@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"..\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"..\\\\\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "gn",
+ "gen",
+ "out/Release"
+ ],
+ "env": {
+ "VSINSTALLDIR": "[CACHE]\\windows_sdk"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[CACHE]\\windows_sdk\\win_sdk\\bin\\x64"
+ ]
+ },
+ "name": "gn"
+ },
+ {
+ "cmd": [
+ "ninja",
+ "-C",
+ "out/Release"
+ ],
+ "env": {
+ "VSINSTALLDIR": "[CACHE]\\windows_sdk"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[CACHE]\\windows_sdk\\win_sdk\\bin\\x64"
+ ]
+ },
+ "name": "ninja"
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipe_modules/windows_sdk/examples/full.py b/infra/luci/recipe_modules/windows_sdk/examples/full.py
new file mode 100644
index 0000000..82ab06b
--- /dev/null
+++ b/infra/luci/recipe_modules/windows_sdk/examples/full.py
@@ -0,0 +1,35 @@
+# 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.
+
+DEPS = [
+ 'windows_sdk',
+ 'recipe_engine/platform',
+ 'recipe_engine/properties',
+ 'recipe_engine/step',
+]
+
+
+def RunSteps(api):
+ with api.windows_sdk():
+ api.step('gn', ['gn', 'gen', 'out/Release'])
+ api.step('ninja', ['ninja', '-C', 'out/Release'])
+
+
+def GenTests(api):
+ for platform in ('linux', 'mac', 'win'):
+ properties = {
+ 'buildername': 'test_builder',
+ }
+ yield (api.test(platform) + api.platform.name(platform) +
+ api.properties.generic(**properties))
\ No newline at end of file
diff --git a/infra/luci/recipes/perfetto.expected/ci_android.json b/infra/luci/recipes/perfetto.expected/ci_android.json
new file mode 100644
index 0000000..3cad1f0
--- /dev/null
+++ b/infra/luci/recipes/perfetto.expected/ci_android.json
@@ -0,0 +1,1702 @@
+[
+ {
+ "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",
+ "refs/heads/master"
+ ],
+ "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": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "git.rev-parse",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/install-build-deps",
+ "--android"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "build-deps"
+ },
+ {
+ "cmd": [],
+ "name": "android-arm"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/android-arm",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"android\" target_cpu=\"arm\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/android-arm",
+ "trace_processor_shell",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "android-arm.Artifact upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-arm/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts//android-arm/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-arm.Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-arm/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/android-arm\", \"root\": \"[CACHE]/builder/perfetto/out/android-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-android-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.Artifact upload.build perfetto/trace_processor_shell/android-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/android-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-android-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.Artifact upload.register perfetto/trace_processor_shell/android-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/android-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/android-arm@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/android-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-arm/stripped/tracebox",
+ "gs://perfetto-luci-artifacts//android-arm/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-arm.Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-arm/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/android-arm\", \"root\": \"[CACHE]/builder/perfetto/out/android-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-android-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.Artifact upload.build perfetto/tracebox/android-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/android-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-android-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.Artifact upload.register perfetto/tracebox/android-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/android-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/android-arm@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/android-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-arm/stripped/perfetto",
+ "gs://perfetto-luci-artifacts//android-arm/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-arm.Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-arm/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/android-arm\", \"root\": \"[CACHE]/builder/perfetto/out/android-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-android-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.Artifact upload.build perfetto/perfetto/android-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/android-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-android-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.Artifact upload.register perfetto/perfetto/android-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/android-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/android-arm@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/android-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-arm/stripped/traced",
+ "gs://perfetto-luci-artifacts//android-arm/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-arm.Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-arm/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/android-arm\", \"root\": \"[CACHE]/builder/perfetto/out/android-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-android-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.Artifact upload.build perfetto/traced/android-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/android-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-android-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.Artifact upload.register perfetto/traced/android-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/android-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/android-arm@https://chrome-infra-packages.appspot.com/p/perfetto/traced/android-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-arm/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts//android-arm/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-arm.Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-arm/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/android-arm\", \"root\": \"[CACHE]/builder/perfetto/out/android-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-android-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.Artifact upload.build perfetto/traced_probes/android-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/android-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-android-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm.Artifact upload.register perfetto/traced_probes/android-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/android-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/android-arm@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/android-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "android-arm64"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/android-arm64",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"android\" target_cpu=\"arm64\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/android-arm64",
+ "trace_processor_shell",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "android-arm64.Artifact upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-arm64/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts//android-arm64/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-arm64.Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-arm64/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/android-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/android-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-android-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.Artifact upload.build perfetto/trace_processor_shell/android-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/android-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-android-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.Artifact upload.register perfetto/trace_processor_shell/android-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/android-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/android-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/android-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-arm64/stripped/tracebox",
+ "gs://perfetto-luci-artifacts//android-arm64/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-arm64.Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-arm64/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/android-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/android-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-android-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.Artifact upload.build perfetto/tracebox/android-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/android-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-android-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.Artifact upload.register perfetto/tracebox/android-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/android-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/android-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/android-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-arm64/stripped/perfetto",
+ "gs://perfetto-luci-artifacts//android-arm64/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-arm64.Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-arm64/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/android-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/android-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-android-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.Artifact upload.build perfetto/perfetto/android-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/android-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-android-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.Artifact upload.register perfetto/perfetto/android-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/android-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/android-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/android-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-arm64/stripped/traced",
+ "gs://perfetto-luci-artifacts//android-arm64/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-arm64.Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-arm64/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/android-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/android-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-android-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.Artifact upload.build perfetto/traced/android-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/android-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-android-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.Artifact upload.register perfetto/traced/android-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/android-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/android-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/traced/android-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-arm64/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts//android-arm64/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-arm64.Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-arm64/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/android-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/android-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-android-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.Artifact upload.build perfetto/traced_probes/android-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/android-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-android-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-arm64.Artifact upload.register perfetto/traced_probes/android-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/android-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/android-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/android-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "android-x86"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/android-x86",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"android\" target_cpu=\"x86\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/android-x86",
+ "trace_processor_shell",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "android-x86.Artifact upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-x86/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts//android-x86/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-x86.Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-x86/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/android-x86\", \"root\": \"[CACHE]/builder/perfetto/out/android-x86/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-android-x86.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.Artifact upload.build perfetto/trace_processor_shell/android-x86",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/android-x86\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-android-x86.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.Artifact upload.register perfetto/trace_processor_shell/android-x86",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/android-x86\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/android-x86@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/android-x86/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-x86/stripped/tracebox",
+ "gs://perfetto-luci-artifacts//android-x86/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-x86.Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-x86/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/android-x86\", \"root\": \"[CACHE]/builder/perfetto/out/android-x86/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-android-x86.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.Artifact upload.build perfetto/tracebox/android-x86",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/android-x86\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-android-x86.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.Artifact upload.register perfetto/tracebox/android-x86",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/android-x86\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/android-x86@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/android-x86/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-x86/stripped/perfetto",
+ "gs://perfetto-luci-artifacts//android-x86/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-x86.Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-x86/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/android-x86\", \"root\": \"[CACHE]/builder/perfetto/out/android-x86/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-android-x86.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.Artifact upload.build perfetto/perfetto/android-x86",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/android-x86\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-android-x86.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.Artifact upload.register perfetto/perfetto/android-x86",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/android-x86\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/android-x86@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/android-x86/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-x86/stripped/traced",
+ "gs://perfetto-luci-artifacts//android-x86/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-x86.Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-x86/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/android-x86\", \"root\": \"[CACHE]/builder/perfetto/out/android-x86/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-android-x86.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.Artifact upload.build perfetto/traced/android-x86",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/android-x86\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-android-x86.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.Artifact upload.register perfetto/traced/android-x86",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/android-x86\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/android-x86@https://chrome-infra-packages.appspot.com/p/perfetto/traced/android-x86/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-x86/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts//android-x86/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-x86.Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-x86/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/android-x86\", \"root\": \"[CACHE]/builder/perfetto/out/android-x86/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-android-x86.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.Artifact upload.build perfetto/traced_probes/android-x86",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/android-x86\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-android-x86.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x86.Artifact upload.register perfetto/traced_probes/android-x86",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/android-x86\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/android-x86@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/android-x86/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "android-x64"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/android-x64",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"android\" target_cpu=\"x64\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/android-x64",
+ "trace_processor_shell",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "android-x64.Artifact upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-x64/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts//android-x64/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-x64.Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-x64/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/android-x64\", \"root\": \"[CACHE]/builder/perfetto/out/android-x64/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-android-x64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.Artifact upload.build perfetto/trace_processor_shell/android-x64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/android-x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-android-x64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.Artifact upload.register perfetto/trace_processor_shell/android-x64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/android-x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/android-x64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/android-x64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-x64/stripped/tracebox",
+ "gs://perfetto-luci-artifacts//android-x64/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-x64.Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-x64/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/android-x64\", \"root\": \"[CACHE]/builder/perfetto/out/android-x64/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-android-x64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.Artifact upload.build perfetto/tracebox/android-x64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/android-x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-android-x64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.Artifact upload.register perfetto/tracebox/android-x64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/android-x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/android-x64@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/android-x64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-x64/stripped/perfetto",
+ "gs://perfetto-luci-artifacts//android-x64/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-x64.Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-x64/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/android-x64\", \"root\": \"[CACHE]/builder/perfetto/out/android-x64/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-android-x64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.Artifact upload.build perfetto/perfetto/android-x64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/android-x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-android-x64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.Artifact upload.register perfetto/perfetto/android-x64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/android-x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/android-x64@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/android-x64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-x64/stripped/traced",
+ "gs://perfetto-luci-artifacts//android-x64/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-x64.Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-x64/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/android-x64\", \"root\": \"[CACHE]/builder/perfetto/out/android-x64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-android-x64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.Artifact upload.build perfetto/traced/android-x64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/android-x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-android-x64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.Artifact upload.register perfetto/traced/android-x64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/android-x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/android-x64@https://chrome-infra-packages.appspot.com/p/perfetto/traced/android-x64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/android-x64/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts//android-x64/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "android-x64.Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//android-x64/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/android-x64\", \"root\": \"[CACHE]/builder/perfetto/out/android-x64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-android-x64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.Artifact upload.build perfetto/traced_probes/android-x64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/android-x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-android-x64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "android-x64.Artifact upload.register perfetto/traced_probes/android-x64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/android-x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/android-x64@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/android-x64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipes/perfetto.expected/ci_linux.json b/infra/luci/recipes/perfetto.expected/ci_linux.json
index eebe765..7005632 100644
--- a/infra/luci/recipes/perfetto.expected/ci_linux.json
+++ b/infra/luci/recipes/perfetto.expected/ci_linux.json
@@ -39,7 +39,7 @@
"fetch",
"--tags",
"https://android.googlesource.com/platform/external/perfetto",
- "2d72510e447ab60a9728aeea2362d8be2cbd7789"
+ "refs/heads/master"
],
"cwd": "[CACHE]/builder/perfetto",
"infra_step": true,
@@ -63,32 +63,1308 @@
},
{
"cmd": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "git.rev-parse",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
"tools/install-build-deps",
- "--ui",
- "--android"
+ "--linux-arm"
],
"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": [],
+ "name": "linux-amd64"
},
{
"cmd": [
- "tools/ninja",
- "-C",
- "out/dist"
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/linux-amd64",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"linux\" target_cpu=\"x64\""
],
"cwd": "[CACHE]/builder/perfetto",
- "name": "ninja"
+ "name": "linux-amd64.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/linux-amd64",
+ "trace_processor_shell",
+ "trace_to_text",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-amd64.Artifact upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts//linux-amd64/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-amd64/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/trace_processor_shell/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/trace_processor_shell/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/trace_to_text",
+ "gs://perfetto-luci-artifacts//linux-amd64/trace_to_text"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-amd64/trace_to_text@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_to_text\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_to_text/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_to_text-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/trace_to_text/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_to_text/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_to_text-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/trace_to_text/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_to_text/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_to_text/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_to_text/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/tracebox",
+ "gs://perfetto-luci-artifacts//linux-amd64/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-amd64/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/tracebox/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/tracebox/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/perfetto",
+ "gs://perfetto-luci-artifacts//linux-amd64/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-amd64/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/perfetto/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/perfetto/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/traced",
+ "gs://perfetto-luci-artifacts//linux-amd64/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-amd64/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/traced/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/traced/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/traced/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts//linux-amd64/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload (6)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-amd64/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/traced_probes/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/traced_probes/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-arm"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/linux-arm",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"linux\" target_cpu=\"arm\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/linux-arm",
+ "trace_processor_shell",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-arm.Artifact upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts//linux-arm/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm.Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-arm/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/linux-arm\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-linux-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.build perfetto/trace_processor_shell/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-linux-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.register perfetto/trace_processor_shell/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/linux-arm@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/linux-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm/stripped/tracebox",
+ "gs://perfetto-luci-artifacts//linux-arm/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm.Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-arm/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/linux-arm\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-linux-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.build perfetto/tracebox/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-linux-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.register perfetto/tracebox/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/linux-arm@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/linux-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm/stripped/perfetto",
+ "gs://perfetto-luci-artifacts//linux-arm/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm.Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-arm/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/linux-arm\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-linux-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.build perfetto/perfetto/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-linux-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.register perfetto/perfetto/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/linux-arm@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/linux-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm/stripped/traced",
+ "gs://perfetto-luci-artifacts//linux-arm/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm.Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-arm/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/linux-arm\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-linux-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.build perfetto/traced/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-linux-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.register perfetto/traced/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/linux-arm@https://chrome-infra-packages.appspot.com/p/perfetto/traced/linux-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts//linux-arm/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm.Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-arm/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/linux-arm\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-linux-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.build perfetto/traced_probes/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-linux-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.register perfetto/traced_probes/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/linux-arm@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/linux-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-arm64"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/linux-arm64",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"linux\" target_cpu=\"arm64\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/linux-arm64",
+ "trace_processor_shell",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-arm64.Artifact upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm64/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts//linux-arm64/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm64.Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-arm64/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/linux-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-linux-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.build perfetto/trace_processor_shell/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-linux-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.register perfetto/trace_processor_shell/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/linux-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/linux-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm64/stripped/tracebox",
+ "gs://perfetto-luci-artifacts//linux-arm64/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm64.Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-arm64/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/linux-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-linux-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.build perfetto/tracebox/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-linux-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.register perfetto/tracebox/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/linux-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/linux-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm64/stripped/perfetto",
+ "gs://perfetto-luci-artifacts//linux-arm64/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm64.Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-arm64/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/linux-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-linux-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.build perfetto/perfetto/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-linux-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.register perfetto/perfetto/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/linux-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/linux-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm64/stripped/traced",
+ "gs://perfetto-luci-artifacts//linux-arm64/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm64.Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-arm64/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/linux-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-linux-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.build perfetto/traced/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-linux-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.register perfetto/traced/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/linux-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/traced/linux-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm64/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts//linux-arm64/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm64.Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//linux-arm64/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/linux-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-linux-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.build perfetto/traced_probes/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-linux-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.register perfetto/traced_probes/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/linux-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/linux-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
},
{
"name": "$result"
diff --git a/infra/luci/recipes/perfetto.expected/ci_mac.json b/infra/luci/recipes/perfetto.expected/ci_mac.json
new file mode 100644
index 0000000..2c67d65
--- /dev/null
+++ b/infra/luci/recipes/perfetto.expected/ci_mac.json
@@ -0,0 +1,618 @@
+[
+ {
+ "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",
+ "refs/heads/master"
+ ],
+ "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": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "git.rev-parse",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/install-build-deps"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "build-deps"
+ },
+ {
+ "cmd": [
+ "cipd",
+ "ensure",
+ "-root",
+ "[CACHE]/macos_sdk",
+ "-ensure-file",
+ "infra/tools/mac_toolchain/${platform} git_revision:e9b1fe29fe21a1cd36428c43ea2aba244bd31280",
+ "-max-threads",
+ "0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "ensure_installed",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"resolved-instance_id-of-git_revision:e9b\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"infra/tools/mac_toolchain/resolved-platform\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "[CACHE]/macos_sdk/mac_toolchain",
+ "install",
+ "-kind",
+ "mac",
+ "-xcode-version",
+ "12b5025f",
+ "-output-dir",
+ "[CACHE]/macos_sdk/XCode.app"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "install xcode"
+ },
+ {
+ "cmd": [
+ "sudo",
+ "xcode-select",
+ "--switch",
+ "[CACHE]/macos_sdk/XCode.app"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "select XCode"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/mac-amd64",
+ "--args=is_debug=false monolithic_binaries=true"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "gn gen"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/mac-amd64",
+ "trace_processor_shell",
+ "trace_to_text",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "ninja"
+ },
+ {
+ "cmd": [
+ "sudo",
+ "xcode-select",
+ "--reset"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "reset XCode"
+ },
+ {
+ "cmd": [],
+ "name": "Artifact upload"
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/mac-amd64/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts//mac-amd64/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//mac-amd64/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/mac-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/mac-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-mac-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.build perfetto/trace_processor_shell/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-mac-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.register perfetto/trace_processor_shell/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/mac-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/mac-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/mac-amd64/stripped/trace_to_text",
+ "gs://perfetto-luci-artifacts//mac-amd64/trace_to_text"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//mac-amd64/trace_to_text@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_to_text\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_to_text/mac-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/mac-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_to_text-mac-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.build perfetto/trace_to_text/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_to_text/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_to_text-mac-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.register perfetto/trace_to_text/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_to_text/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_to_text/mac-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_to_text/mac-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/mac-amd64/stripped/tracebox",
+ "gs://perfetto-luci-artifacts//mac-amd64/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//mac-amd64/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/mac-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/mac-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-mac-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.build perfetto/tracebox/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-mac-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.register perfetto/tracebox/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/mac-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/mac-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/mac-amd64/stripped/perfetto",
+ "gs://perfetto-luci-artifacts//mac-amd64/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//mac-amd64/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/mac-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/mac-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-mac-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.build perfetto/perfetto/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-mac-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.register perfetto/perfetto/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/mac-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/mac-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/mac-amd64/stripped/traced",
+ "gs://perfetto-luci-artifacts//mac-amd64/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//mac-amd64/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/mac-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/mac-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-mac-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.build perfetto/traced/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-mac-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.register perfetto/traced/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/mac-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/traced/mac-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/mac-amd64/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts//mac-amd64/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "Artifact upload.gsutil upload (6)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//mac-amd64/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/mac-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/mac-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-mac-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.build perfetto/traced_probes/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-mac-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "Artifact upload.register perfetto/traced_probes/mac-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/mac-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/mac-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/mac-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipes/perfetto.expected/ci_tag.json b/infra/luci/recipes/perfetto.expected/ci_tag.json
new file mode 100644
index 0000000..1c07200
--- /dev/null
+++ b/infra/luci/recipes/perfetto.expected/ci_tag.json
@@ -0,0 +1,1404 @@
+[
+ {
+ "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",
+ "refs/tags/v13.0"
+ ],
+ "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": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "git.rev-parse",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/install-build-deps",
+ "--linux-arm"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "build-deps"
+ },
+ {
+ "cmd": [],
+ "name": "linux-amd64"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/linux-amd64",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"linux\" target_cpu=\"x64\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/linux-amd64",
+ "trace_processor_shell",
+ "trace_to_text",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-amd64.Artifact upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts/v13.0/linux-amd64/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-amd64/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/trace_processor_shell/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/trace_processor_shell/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/trace_to_text",
+ "gs://perfetto-luci-artifacts/v13.0/linux-amd64/trace_to_text"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-amd64/trace_to_text@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_to_text\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_to_text/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_to_text-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/trace_to_text/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_to_text/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_to_text-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/trace_to_text/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_to_text/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_to_text/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_to_text/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/tracebox",
+ "gs://perfetto-luci-artifacts/v13.0/linux-amd64/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-amd64/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/tracebox/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/tracebox/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/perfetto",
+ "gs://perfetto-luci-artifacts/v13.0/linux-amd64/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-amd64/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/perfetto/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/perfetto/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/traced",
+ "gs://perfetto-luci-artifacts/v13.0/linux-amd64/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-amd64/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/traced/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/traced/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/traced/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-amd64/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts/v13.0/linux-amd64/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-amd64.Artifact upload.gsutil upload (6)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-amd64/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/linux-amd64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-amd64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-linux-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.build perfetto/traced_probes/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-linux-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.Artifact upload.register perfetto/traced_probes/linux-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/linux-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/linux-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-arm"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/linux-arm",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"linux\" target_cpu=\"arm\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/linux-arm",
+ "trace_processor_shell",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-arm.Artifact upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts/v13.0/linux-arm/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm.Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-arm/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/linux-arm\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-linux-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.build perfetto/trace_processor_shell/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-linux-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.register perfetto/trace_processor_shell/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/linux-arm@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/linux-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm/stripped/tracebox",
+ "gs://perfetto-luci-artifacts/v13.0/linux-arm/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm.Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-arm/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/linux-arm\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-linux-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.build perfetto/tracebox/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-linux-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.register perfetto/tracebox/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/linux-arm@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/linux-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm/stripped/perfetto",
+ "gs://perfetto-luci-artifacts/v13.0/linux-arm/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm.Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-arm/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/linux-arm\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-linux-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.build perfetto/perfetto/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-linux-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.register perfetto/perfetto/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/linux-arm@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/linux-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm/stripped/traced",
+ "gs://perfetto-luci-artifacts/v13.0/linux-arm/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm.Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-arm/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/linux-arm\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-linux-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.build perfetto/traced/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-linux-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.register perfetto/traced/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/linux-arm@https://chrome-infra-packages.appspot.com/p/perfetto/traced/linux-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts/v13.0/linux-arm/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm.Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-arm/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/linux-arm\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-linux-arm.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.build perfetto/traced_probes/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-linux-arm.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.Artifact upload.register perfetto/traced_probes/linux-arm",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-arm\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/linux-arm@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/linux-arm/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-arm64"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/linux-arm64",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"linux\" target_cpu=\"arm64\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/linux-arm64",
+ "trace_processor_shell",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-arm64.Artifact upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm64/stripped/trace_processor_shell",
+ "gs://perfetto-luci-artifacts/v13.0/linux-arm64/trace_processor_shell"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm64.Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-arm64/trace_processor_shell@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/linux-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/trace_processor_shell-linux-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.build perfetto/trace_processor_shell/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/trace_processor_shell-linux-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.register perfetto/trace_processor_shell/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/linux-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/linux-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm64/stripped/tracebox",
+ "gs://perfetto-luci-artifacts/v13.0/linux-arm64/tracebox"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm64.Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-arm64/tracebox@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"tracebox\"}], \"install_mode\": \"\", \"package\": \"perfetto/tracebox/linux-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/tracebox-linux-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.build perfetto/tracebox/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/tracebox-linux-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.register perfetto/tracebox/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/tracebox/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/tracebox/linux-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/tracebox/linux-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm64/stripped/perfetto",
+ "gs://perfetto-luci-artifacts/v13.0/linux-arm64/perfetto"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm64.Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-arm64/perfetto@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/linux-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/perfetto-linux-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.build perfetto/perfetto/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/perfetto-linux-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.register perfetto/perfetto/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/linux-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/linux-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm64/stripped/traced",
+ "gs://perfetto-luci-artifacts/v13.0/linux-arm64/traced"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm64.Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-arm64/traced@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/linux-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced-linux-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.build perfetto/traced/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced-linux-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.register perfetto/traced/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/linux-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/traced/linux-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]/builder/perfetto/out/linux-arm64/stripped/traced_probes",
+ "gs://perfetto-luci-artifacts/v13.0/linux-arm64/traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "linux-arm64.Artifact upload.gsutil upload (5)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts/v13.0/linux-arm64/traced_probes@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced_probes\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced_probes/linux-arm64\", \"root\": \"[CACHE]/builder/perfetto/out/linux-arm64/stripped\"}",
+ "-out",
+ "[CLEANUP]/traced_probes-linux-arm64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.build perfetto/traced_probes/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "pkg-register",
+ "[CLEANUP]/traced_probes-linux-arm64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-tag",
+ "git_tag:v13.0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.Artifact upload.register perfetto/traced_probes/linux-arm64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced_probes/linux-arm64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced_probes/linux-arm64@https://chrome-infra-packages.appspot.com/p/perfetto/traced_probes/linux-arm64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipes/perfetto.expected/ci_win.json b/infra/luci/recipes/perfetto.expected/ci_win.json
new file mode 100644
index 0000000..cb93f16
--- /dev/null
+++ b/infra/luci/recipes/perfetto.expected/ci_win.json
@@ -0,0 +1,485 @@
+[
+ {
+ "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",
+ "refs/heads/master"
+ ],
+ "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": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "infra_step": true,
+ "name": "git.rev-parse",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/install-build-deps"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "infra_step": true,
+ "name": "build-deps"
+ },
+ {
+ "cmd": [
+ "cipd.bat",
+ "ensure",
+ "-root",
+ "[CACHE]\\windows_sdk",
+ "-ensure-file",
+ "chrome_internal/third_party/sdk/windows uploaded:2019-09-06",
+ "-max-threads",
+ "0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "infra_step": true,
+ "name": "ensure_installed",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"resolved-instance_id-of-uploaded:2019-09\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"chrome_internal/third_party/sdk/windows\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "\nimport shutil\nimport sys\nshutil.copy(sys.argv[1], sys.argv[2])\n",
+ "[CACHE]\\windows_sdk\\win_sdk\\bin\\SetEnv.x64.json",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "name": "read SetEnv.x64.json",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"env\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"PATH\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ [@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"..\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"..\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"win_sdk\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"bin\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"x64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ ], @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"VSINSTALLDIR\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ [@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"..\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"..\\\\\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]\\builder\\perfetto\\out\\windows-amd64",
+ "--args=is_debug=false monolithic_binaries=true"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "env": {
+ "VSINSTALLDIR": "[CACHE]\\windows_sdk"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[CACHE]\\windows_sdk\\win_sdk\\bin\\x64"
+ ]
+ },
+ "name": "gn gen"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]\\builder\\perfetto\\out\\windows-amd64",
+ "trace_processor_shell",
+ "trace_to_text",
+ "perfetto",
+ "traced"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "env": {
+ "VSINSTALLDIR": "[CACHE]\\windows_sdk"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[CACHE]\\windows_sdk\\win_sdk\\bin\\x64"
+ ]
+ },
+ "name": "ninja"
+ },
+ {
+ "cmd": [],
+ "name": "Artifact upload"
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]\\resources\\gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]\\gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]\\builder\\perfetto\\out\\windows-amd64\\trace_processor_shell.exe",
+ "gs://perfetto-luci-artifacts//windows-amd64/trace_processor_shell.exe"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "infra_step": true,
+ "name": "Artifact upload.gsutil upload",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//windows-amd64/trace_processor_shell.exe@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd.bat",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_processor_shell.exe\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_processor_shell/windows-amd64\", \"root\": \"[CACHE]\\\\builder\\\\perfetto\\\\out\\\\windows-amd64\"}",
+ "-out",
+ "[CLEANUP]\\trace_processor_shell-windows-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "name": "Artifact upload.build perfetto/trace_processor_shell/windows-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/windows-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd.bat",
+ "pkg-register",
+ "[CLEANUP]\\trace_processor_shell-windows-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "name": "Artifact upload.register perfetto/trace_processor_shell/windows-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_processor_shell/windows-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_processor_shell/windows-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_processor_shell/windows-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]\\resources\\gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]\\gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]\\builder\\perfetto\\out\\windows-amd64\\trace_to_text.exe",
+ "gs://perfetto-luci-artifacts//windows-amd64/trace_to_text.exe"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "infra_step": true,
+ "name": "Artifact upload.gsutil upload (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//windows-amd64/trace_to_text.exe@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd.bat",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"trace_to_text.exe\"}], \"install_mode\": \"\", \"package\": \"perfetto/trace_to_text/windows-amd64\", \"root\": \"[CACHE]\\\\builder\\\\perfetto\\\\out\\\\windows-amd64\"}",
+ "-out",
+ "[CLEANUP]\\trace_to_text-windows-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "name": "Artifact upload.build perfetto/trace_to_text/windows-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_to_text/windows-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd.bat",
+ "pkg-register",
+ "[CLEANUP]\\trace_to_text-windows-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "name": "Artifact upload.register perfetto/trace_to_text/windows-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/trace_to_text/windows-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/trace_to_text/windows-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/trace_to_text/windows-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]\\resources\\gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]\\gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]\\builder\\perfetto\\out\\windows-amd64\\perfetto.exe",
+ "gs://perfetto-luci-artifacts//windows-amd64/perfetto.exe"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "infra_step": true,
+ "name": "Artifact upload.gsutil upload (3)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//windows-amd64/perfetto.exe@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd.bat",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"perfetto.exe\"}], \"install_mode\": \"\", \"package\": \"perfetto/perfetto/windows-amd64\", \"root\": \"[CACHE]\\\\builder\\\\perfetto\\\\out\\\\windows-amd64\"}",
+ "-out",
+ "[CLEANUP]\\perfetto-windows-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "name": "Artifact upload.build perfetto/perfetto/windows-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/windows-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd.bat",
+ "pkg-register",
+ "[CLEANUP]\\perfetto-windows-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "name": "Artifact upload.register perfetto/perfetto/windows-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/perfetto/windows-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/perfetto/windows-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/perfetto/windows-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]\\resources\\gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]\\gsutil.py",
+ "----",
+ "cp",
+ "[CACHE]\\builder\\perfetto\\out\\windows-amd64\\traced.exe",
+ "gs://perfetto-luci-artifacts//windows-amd64/traced.exe"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "infra_step": true,
+ "name": "Artifact upload.gsutil upload (4)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/perfetto-luci-artifacts//windows-amd64/traced.exe@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd.bat",
+ "pkg-build",
+ "-pkg-def",
+ "{\"data\": [{\"file\": \"traced.exe\"}], \"install_mode\": \"\", \"package\": \"perfetto/traced/windows-amd64\", \"root\": \"[CACHE]\\\\builder\\\\perfetto\\\\out\\\\windows-amd64\"}",
+ "-out",
+ "[CLEANUP]\\traced-windows-amd64.cipd",
+ "-hash-algo",
+ "sha256",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "name": "Artifact upload.build perfetto/traced/windows-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/windows-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd.bat",
+ "pkg-register",
+ "[CLEANUP]\\traced-windows-amd64.cipd",
+ "-ref",
+ "latest",
+ "-tag",
+ "git_revision:",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[CACHE]\\builder\\perfetto",
+ "name": "Artifact upload.register perfetto/traced/windows-amd64",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"40-chars-fake-of-the-package-instance_id\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"perfetto/traced/windows-amd64\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LINK@perfetto/traced/windows-amd64@https://chrome-infra-packages.appspot.com/p/perfetto/traced/windows-amd64/+/40-chars-fake-of-the-package-instance_id@@@"
+ ]
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipes/perfetto.expected/unofficial.json b/infra/luci/recipes/perfetto.expected/unofficial.json
new file mode 100644
index 0000000..497a920
--- /dev/null
+++ b/infra/luci/recipes/perfetto.expected/unofficial.json
@@ -0,0 +1,199 @@
+[
+ {
+ "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",
+ "refs/heads/master"
+ ],
+ "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": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "git.rev-parse",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/install-build-deps",
+ "--linux-arm"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "infra_step": true,
+ "name": "build-deps"
+ },
+ {
+ "cmd": [],
+ "name": "linux-amd64"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/linux-amd64",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"linux\" target_cpu=\"x64\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/linux-amd64",
+ "trace_processor_shell",
+ "trace_to_text",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-amd64.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-arm"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/linux-arm",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"linux\" target_cpu=\"arm\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/linux-arm",
+ "trace_processor_shell",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "linux-arm64"
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/gn",
+ "gen",
+ "[CACHE]/builder/perfetto/out/linux-arm64",
+ "--args=is_debug=false monolithic_binaries=true target_os=\"linux\" target_cpu=\"arm64\""
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.gn gen",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "tools/ninja",
+ "-C",
+ "[CACHE]/builder/perfetto/out/linux-arm64",
+ "trace_processor_shell",
+ "tracebox",
+ "perfetto",
+ "traced",
+ "traced_probes"
+ ],
+ "cwd": "[CACHE]/builder/perfetto",
+ "name": "linux-arm64.ninja",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/infra/luci/recipes/perfetto.py b/infra/luci/recipes/perfetto.py
index e4552d8..3ad2f9f 100644
--- a/infra/luci/recipes/perfetto.py
+++ b/infra/luci/recipes/perfetto.py
@@ -16,13 +16,18 @@
from recipe_engine.recipe_api import Property
DEPS = [
+ 'depot_tools/gsutil',
'recipe_engine/buildbucket',
+ 'recipe_engine/cipd',
'recipe_engine/context',
'recipe_engine/file',
'recipe_engine/path',
'recipe_engine/platform',
'recipe_engine/properties',
+ 'recipe_engine/raw_io',
'recipe_engine/step',
+ 'macos_sdk',
+ 'windows_sdk',
]
PROPERTIES = {
@@ -33,13 +38,136 @@
),
}
-ARTIFACTS = ['trace_processor_shell']
+ARTIFACTS = [
+ {
+ 'name': 'trace_processor_shell'
+ },
+ {
+ 'name':
+ 'trace_to_text',
+
+ # trace_to_text is really a host exeutable, doesn't make sense to build
+ # it when cross-compiling .
+ 'exclude_platforms': [
+ 'android-arm', 'android-arm64', 'android-x86', 'android-x64',
+ 'linux-arm', 'linux-arm64'
+ ]
+ },
+ {
+ 'name': 'tracebox',
+ 'exclude_platforms': ['windows-amd64']
+ },
+ {
+ 'name': 'perfetto'
+ },
+ {
+ 'name': 'traced'
+ },
+ {
+ 'name': 'traced_probes',
+ 'exclude_platforms': ['windows-amd64']
+ },
+]
+
+
+class BuildContext:
+
+ def __init__(self, src_dir):
+ self.src_dir = src_dir
+ self.git_revision = None
+ self.maybe_git_tag = None
+
+
+def GnArgs(platform):
+ (os, cpu) = platform.split('-')
+ base_args = 'is_debug=false monolithic_binaries=true'
+ if os not in ('android', 'linux'):
+ return base_args # No cross-compiling on Mac and Windows.
+ cpu = 'x64' if cpu == 'amd64' else cpu # GN calls it "x64".
+ return base_args + ' target_os="{}" target_cpu="{}"'.format(os, cpu)
+
+
+def UploadArtifact(api, ctx, platform, out_dir, artifact):
+ exclude_platforms = artifact.get('exclude_platforms', [])
+ if platform in exclude_platforms:
+ return
+
+ # We want to use the stripped binaries except on Windows where we don't generate
+ # them.
+ exe_dir = out_dir if api.platform.is_win else out_dir.join('stripped')
+
+ # Compute the exact artifact path
+ gcs_upload_dir = ctx.maybe_git_tag if ctx.maybe_git_tag else ctx.git_revision
+ artifact_ext = artifact['name'] + ('.exe' if api.platform.is_win else '')
+ source_path = exe_dir.join(artifact_ext)
+
+ # Upload to GCS bucket.
+ gcs_target_path = '{}/{}/{}'.format(gcs_upload_dir, platform, artifact_ext)
+ api.gsutil.upload(source_path, 'perfetto-luci-artifacts', gcs_target_path)
+
+ # Create the CIPD package definition from the artifact path.
+ cipd_pkg_name = 'perfetto/{}/{}'.format(artifact['name'], platform)
+ pkg_def = api.cipd.PackageDefinition(
+ package_name=cipd_pkg_name, package_root=exe_dir)
+ pkg_def.add_file(source_path)
+
+ # Actually build the CIPD pakcage
+ cipd_pkg_file_name = '{}-{}.cipd'.format(artifact['name'], platform)
+ cipd_pkg_file = api.path['cleanup'].join(cipd_pkg_file_name)
+ api.cipd.build_from_pkg(
+ pkg_def=pkg_def,
+ output_package=cipd_pkg_file,
+ )
+
+ # If we have a git tag, add that to the CIPD tags.
+ tags = {
+ 'git_revision': ctx.git_revision,
+ }
+ if ctx.maybe_git_tag:
+ tags['git_tag'] = ctx.maybe_git_tag
+
+ # Upload the package and regisiter with the 'latest' tag.
+ api.cipd.register(
+ package_name=cipd_pkg_name,
+ package_path=cipd_pkg_file,
+ refs=['latest'],
+ tags=tags,
+ )
+
+
+def BuildForPlatform(api, ctx, platform):
+ out_dir = ctx.src_dir.join('out', platform)
+
+ # Build Perfetto.
+ # There should be no need for internet access here.
+
+ with api.context(cwd=ctx.src_dir), api.macos_sdk(), api.windows_sdk():
+ targets = [
+ x['name']
+ for x in ARTIFACTS
+ if platform not in x.get('exclude_platforms', [])
+ ]
+ args = GnArgs(platform)
+ api.step('gn gen',
+ ['python3', 'tools/gn', 'gen', out_dir, '--args={}'.format(args)])
+ api.step('ninja', ['python3', 'tools/ninja', '-C', out_dir] + targets)
+
+ # Upload stripped artifacts using gsutil if we're on the official builder.
+ if 'official' not in api.buildbucket.builder_id.builder:
+ return
+
+ with api.step.nest('Artifact upload'), api.context(cwd=ctx.src_dir):
+ for artifact in ARTIFACTS:
+ UploadArtifact(api, ctx, platform, out_dir, artifact)
def RunSteps(api, repository):
builder_cache_dir = api.path['cache'].join('builder')
src_dir = builder_cache_dir.join('perfetto')
+ # Crate the context we use in all the building stages.
+ ctx = BuildContext(src_dir)
+
# Fetch the Perfetto repo.
with api.step.nest('git'), api.context(infra_steps=True):
api.file.ensure_directory('ensure source dir', src_dir)
@@ -47,28 +175,69 @@
with api.context(cwd=src_dir):
build_input = api.buildbucket.build_input
ref = (
- build_input.gitiles_commit.id
+ build_input.gitiles_commit.ref
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'])
+ # Store information about the git revision and the tag if available.
+ ctx.git_revision = api.step(
+ 'rev-parse', ['git', 'rev-parse', 'HEAD'],
+ stdout=api.raw_io.output()).stdout.strip()
+ ctx.maybe_git_tag = ref.replace(
+ 'refs/tags/', '') if ref.startswith('refs/tags/') else None
- # 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'])
+ # Pull all deps here.
+ with api.context(cwd=src_dir, infra_steps=True):
+ extra_args = []
+ if 'android' in api.buildbucket.builder_id.builder:
+ extra_args += ['--android']
+ elif api.platform.is_linux:
+ # Pull the cross-toolchains for building for linux-arm{,64}.
+ extra_args += ['--linux-arm']
+ api.step('build-deps', ['python3', 'tools/install-build-deps'] + extra_args)
+
+ if api.platform.is_win:
+ BuildForPlatform(api, ctx, 'windows-amd64')
+ elif api.platform.is_mac:
+ BuildForPlatform(api, ctx, 'mac-amd64')
+ elif 'android' in api.buildbucket.builder_id.builder:
+ with api.step.nest('android-arm'):
+ BuildForPlatform(api, ctx, 'android-arm')
+ with api.step.nest('android-arm64'):
+ BuildForPlatform(api, ctx, 'android-arm64')
+ with api.step.nest('android-x86'):
+ BuildForPlatform(api, ctx, 'android-x86')
+ with api.step.nest('android-x64'):
+ BuildForPlatform(api, ctx, 'android-x64')
+ elif api.platform.is_linux:
+ with api.step.nest('linux-amd64'):
+ BuildForPlatform(api, ctx, 'linux-amd64')
+ with api.step.nest('linux-arm'):
+ BuildForPlatform(api, ctx, 'linux-arm')
+ with api.step.nest('linux-arm64'):
+ BuildForPlatform(api, ctx, 'linux-arm64')
def GenTests(api):
- for platform in ('linux',):
- yield (api.test('ci_' + platform) + api.platform.name(platform) +
+ for target in ('android', 'linux', 'mac', 'win'):
+ host = 'linux' if target == 'android' else target
+ yield (api.test('ci_' + target) + api.platform.name(host) +
api.buildbucket.ci_build(
project='perfetto',
+ builder='perfetto-official-builder-%s' % target,
git_repo='android.googlesource.com/platform/external/perfetto',
))
+
+ yield (api.test('ci_tag') + api.platform.name('linux') +
+ api.buildbucket.ci_build(
+ project='perfetto',
+ builder='official',
+ git_repo='android.googlesource.com/platform/external/perfetto',
+ git_ref='refs/tags/v13.0'))
+
+ yield (api.test('unofficial') + api.platform.name('linux') +
+ api.buildbucket.ci_build(
+ project='perfetto',
+ git_repo='android.googlesource.com/platform/external/perfetto'))
diff --git a/perfetto.rc b/perfetto.rc
index e8762fb..55ff78f 100644
--- a/perfetto.rc
+++ b/perfetto.rc
@@ -19,7 +19,7 @@
socket traced_producer stream 0666 root root
user nobody
group nobody
- writepid /dev/cpuset/system-background/tasks
+ task_profiles ServiceCapacityLow
service traced_probes /system/bin/traced_probes
class late_start
@@ -28,7 +28,7 @@
# Despite the "log" group below, traced_probes is allowed to read log
# only on userdebug/eng via selinux (see traced_probes.te).
group nobody readproc log
- writepid /dev/cpuset/system-background/tasks
+ task_profiles ServiceCapacityLow
# Clean up procfs configuration even if traced_probes crashes
# unexpectedly.
onrestart exec_background - nobody shell -- /system/bin/traced_probes --cleanup-after-crash
diff --git a/protos/perfetto/common/perf_events.proto b/protos/perfetto/common/perf_events.proto
index 77f3a1e..0d594c9 100644
--- a/protos/perfetto/common/perf_events.proto
+++ b/protos/perfetto/common/perf_events.proto
@@ -47,7 +47,13 @@
oneof event {
Counter counter = 4;
Tracepoint tracepoint = 3;
+ RawEvent raw_event = 5;
}
+
+ // Optional arbitrary name for the event, to identify it in the parsed
+ // trace. Does *not* affect the profiling itself. If unset, the trace
+ // parser will choose a suitable name.
+ optional string name = 10;
}
enum Counter {
@@ -73,4 +79,14 @@
// https://www.kernel.org/doc/Documentation/trace/events.txt
optional string filter = 2;
}
+
+ // Syscall-level description of the event, propagated to the perf_event_attr
+ // struct. Primarily for local use-cases, since the event availability and
+ // encoding is hardware-specific.
+ message RawEvent {
+ optional uint32 type = 1;
+ optional uint64 config = 2;
+ optional uint64 config1 = 3;
+ optional uint64 config2 = 4;
+ }
}
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index c8b55e3..2394168 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -833,7 +833,13 @@
oneof event {
Counter counter = 4;
Tracepoint tracepoint = 3;
+ RawEvent raw_event = 5;
}
+
+ // Optional arbitrary name for the event, to identify it in the parsed
+ // trace. Does *not* affect the profiling itself. If unset, the trace
+ // parser will choose a suitable name.
+ optional string name = 10;
}
enum Counter {
@@ -859,6 +865,16 @@
// https://www.kernel.org/doc/Documentation/trace/events.txt
optional string filter = 2;
}
+
+ // Syscall-level description of the event, propagated to the perf_event_attr
+ // struct. Primarily for local use-cases, since the event availability and
+ // encoding is hardware-specific.
+ message RawEvent {
+ optional uint32 type = 1;
+ optional uint64 config = 2;
+ optional uint64 config1 = 3;
+ optional uint64 config2 = 4;
+ }
}
// End of protos/perfetto/common/perf_events.proto
@@ -939,6 +955,14 @@
// If unset, the cached state will not be cleared.
optional uint32 unwind_state_clear_period_ms = 10;
+ // If set, only profile target if it was installed by a package with one of
+ // these names. Special values:
+ // * "@system": installed on the system partition
+ // * "@product": installed on the product partition
+ // * "@null": sideloaded
+ // Supported on Android 12+.
+ repeated string target_installed_by = 18;
+
//
// Deprecated (superseded by options above):
//
@@ -952,14 +976,6 @@
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;
@@ -1474,7 +1490,7 @@
// 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: 34.
message TraceConfig {
message BufferConfig {
optional uint32 size_kb = 1;
@@ -1874,10 +1890,17 @@
// 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;
+ // `-T filter_out.escaped_string` (for .pbtx). See go/trace-filtering for
+ // design.
+ //
+ // Introduced in Android S, but it was broken (b/195065199). Reintroduced in
+ // Android T with a different field number.
+ message TraceFilter {
+ optional bytes bytecode = 1;
+ }
+ // old field number for trace_filter
+ reserved 32;
+ optional TraceFilter trace_filter = 33;
}
// End of protos/perfetto/config/trace_config.proto
diff --git a/protos/perfetto/config/profiling/perf_event_config.proto b/protos/perfetto/config/profiling/perf_event_config.proto
index 754d948..a936b5b 100644
--- a/protos/perfetto/config/profiling/perf_event_config.proto
+++ b/protos/perfetto/config/profiling/perf_event_config.proto
@@ -94,6 +94,14 @@
// If unset, the cached state will not be cleared.
optional uint32 unwind_state_clear_period_ms = 10;
+ // If set, only profile target if it was installed by a package with one of
+ // these names. Special values:
+ // * "@system": installed on the system partition
+ // * "@product": installed on the product partition
+ // * "@null": sideloaded
+ // Supported on Android 12+.
+ repeated string target_installed_by = 18;
+
//
// Deprecated (superseded by options above):
//
@@ -107,14 +115,6 @@
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;
diff --git a/protos/perfetto/config/trace_config.proto b/protos/perfetto/config/trace_config.proto
index dbc1bab..e845f17 100644
--- a/protos/perfetto/config/trace_config.proto
+++ b/protos/perfetto/config/trace_config.proto
@@ -16,17 +16,17 @@
syntax = "proto2";
-import "protos/perfetto/config/data_source_config.proto";
-import "protos/perfetto/common/builtin_clock.proto";
-
package perfetto.protos;
+import "protos/perfetto/common/builtin_clock.proto";
+import "protos/perfetto/config/data_source_config.proto";
+
// The overall config that is used when starting a new tracing session through
// ProducerPort::StartTracing().
// It contains the general config for the logging buffer(s) and the configs for
// all the data source being enabled.
//
-// Next id: 33.
+// Next id: 34.
message TraceConfig {
message BufferConfig {
optional uint32 size_kb = 1;
@@ -426,8 +426,15 @@
// 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;
+ // `-T filter_out.escaped_string` (for .pbtx). See go/trace-filtering for
+ // design.
+ //
+ // Introduced in Android S, but it was broken (b/195065199). Reintroduced in
+ // Android T with a different field number.
+ message TraceFilter {
+ optional bytes bytecode = 1;
+ }
+ // old field number for trace_filter
+ reserved 32;
+ optional TraceFilter trace_filter = 33;
}
diff --git a/protos/perfetto/ipc/consumer_port.proto b/protos/perfetto/ipc/consumer_port.proto
index 41242e7..9f6d533 100644
--- a/protos/perfetto/ipc/consumer_port.proto
+++ b/protos/perfetto/ipc/consumer_port.proto
@@ -261,7 +261,7 @@
// or something failed.
message SaveTraceForBugreportResponse {
// If true, an eligible the trace was saved into a known location (on Android
- // /data/misc/perfetto-traces, see kBugreportTracePath).
+ // /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;
diff --git a/protos/perfetto/ipc/producer_port.proto b/protos/perfetto/ipc/producer_port.proto
index 9be72ea..f072be0 100644
--- a/protos/perfetto/ipc/producer_port.proto
+++ b/protos/perfetto/ipc/producer_port.proto
@@ -128,16 +128,11 @@
// If provided, overrides the service's SMB scraping setting for the producer.
optional ProducerSMBScrapingMode smb_scraping_mode = 4;
- enum ProducerBuildFlags {
- BUILD_FLAGS_UNSPECIFIED = 0;
- BUILD_FLAGS_DCHECKS_ON = 1;
- BUILD_FLAGS_DCHECKS_OFF = 2;
- }
-
- // If provided, reports the build flags of the producer. It's used merely for
- // error reporting, to print a log message when a producer connects to a
- // service that has mismatching build flags.
- optional ProducerBuildFlags build_flags = 5;
+ // Was build_flags = BUILD_FLAGS_DCHECKS_ON|OFF. It was used to emit an error
+ // when DCHECKs level didn't match between service and producer (in turn that
+ // would crash the service when applying patches).
+ // Removed in v20 as part of b/197340286.
+ reserved 5;
// ---------------------------------------------------
// All fields below have been introduced in Android R.
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 5e45f9c..aa97665 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -37,14 +37,17 @@
"lmk_reason_metric.proto",
"mem_metric.proto",
"mem_unagg_metric.proto",
+ "multiuser_metric.proto",
"package_list.proto",
"powrails_metric.proto",
"process_metadata.proto",
+ "profiler_smaps.proto",
"startup_metric.proto",
"surfaceflinger.proto",
"sysui_cuj_metrics.proto",
"task_names.proto",
"thread_time_in_state_metric.proto",
+ "trace_quality.proto",
"unsymbolized_frames.proto",
]
}
diff --git a/protos/perfetto/metrics/android/g2d_metric.proto b/protos/perfetto/metrics/android/g2d_metric.proto
index e7a2d6a..29b3888 100644
--- a/protos/perfetto/metrics/android/g2d_metric.proto
+++ b/protos/perfetto/metrics/android/g2d_metric.proto
@@ -23,25 +23,32 @@
// 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;
+
+ optional double max_dur_ms = 7;
+ optional double min_dur_ms = 8;
+ optional double avg_dur_ms = 9;
+
+ // Removed: was int64 versions of max_dur_ns, min_dur_ns and avg_dur_ns.
+ reserved 2 to 4;
}
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;
+
+ // max/min/avg G2d frame durations for all instances.
+ optional double max_dur_ms = 7;
+ optional double min_dur_ms = 8;
+ optional double avg_dur_ms = 9;
+
+ // Removed: was int64 versions of max_dur_ns, min_dur_ns and avg_dur_ns.
+ reserved 2 to 4;
}
optional G2dMetric g2d_hw = 1;
diff --git a/protos/perfetto/metrics/android/gpu_metric.proto b/protos/perfetto/metrics/android/gpu_metric.proto
index 2365855..2aaaeaf 100644
--- a/protos/perfetto/metrics/android/gpu_metric.proto
+++ b/protos/perfetto/metrics/android/gpu_metric.proto
@@ -36,4 +36,33 @@
optional int64 mem_max = 2;
optional int64 mem_min = 3;
optional int64 mem_avg = 4;
+
+ message FrequencyMetric {
+ // Identifier for GPU in a multi-gpu device.
+ optional uint32 gpu_id = 1;
+
+ // max/min/avg GPU frequency for this gpu_id
+ // the calculation of avg is weighted by the duration of each frequency
+ optional int64 freq_max = 2;
+ optional int64 freq_min = 3;
+ optional double freq_avg = 4;
+
+ message MetricsPerFrequency {
+ // Used frequency
+ optional int64 freq = 1;
+
+ // Total duration in ms when the state of GPU was in this frequency
+ optional double dur_ms = 2;
+
+ // Percentage of duration in this frequency compared to all frequencies
+ // in this gpu_id
+ optional double percentage = 3;
+ }
+
+ // Metrics for each used GPU frequency
+ repeated MetricsPerFrequency used_freqs = 5;
+ }
+
+ // GPU frequency metric for each gpu_id
+ repeated FrequencyMetric freq_metrics = 5;
}
diff --git a/protos/perfetto/metrics/android/hwcomposer.proto b/protos/perfetto/metrics/android/hwcomposer.proto
index 72edc6d..d9812a8 100644
--- a/protos/perfetto/metrics/android/hwcomposer.proto
+++ b/protos/perfetto/metrics/android/hwcomposer.proto
@@ -59,4 +59,24 @@
// the average of hwcomposer execution time for separated validation cases.
optional double avg_separated_execution_time_ms = 13;
+
+ message DpuVoteMetrics {
+ // the thread ID that handles this track
+ optional uint32 tid = 1;
+
+ // the weighted average of DPU Vote Clock
+ optional double avg_dpu_vote_clock = 2;
+
+ // the weighted average of DPU Vote Avg Bandwidth
+ optional double avg_dpu_vote_avg_bw = 3;
+
+ // the weighted average of DPU Vote Peak Bandwidth
+ optional double avg_dpu_vote_peak_bw = 4;
+
+ // the weighted average of DPU Vote RT (Real Time) Bandwidth
+ optional double avg_dpu_vote_rt_bw = 5;
+ }
+
+ // DPU Vote Metrics for each thread track
+ repeated DpuVoteMetrics dpu_vote_metrics = 14;
}
diff --git a/protos/perfetto/metrics/android/multiuser_metric.proto b/protos/perfetto/metrics/android/multiuser_metric.proto
new file mode 100644
index 0000000..eba37d9
--- /dev/null
+++ b/protos/perfetto/metrics/android/multiuser_metric.proto
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+// Metrics for Multiuser events, such as switching users.
+message AndroidMultiuserMetric {
+
+ // Holds the data for a Multiuser event.
+ message EventData {
+ // Duration of the event (in milliseconds).
+ optional int32 duration_ms = 1;
+
+ // CPU usage of each process during the event.
+ message CpuUsage {
+ // The userId of the process (e.g. 0 or 10).
+ optional int32 user_id = 1;
+ // The name of the process.
+ optional string process_name = 2;
+ // The number of CPU cycles (in megacycles) spent by that process during the event.
+ optional int32 cpu_mcycles = 3;
+ // The ratio of this process's cycles to the total for all processes, expressed as a percentage.
+ optional float cpu_percentage = 4;
+ }
+ repeated CpuUsage cpu_usage = 2;
+ }
+
+ // Metrics for a user switch.
+ optional EventData user_switch = 1;
+}
\ No newline at end of file
diff --git a/protos/perfetto/metrics/android/powrails_metric.proto b/protos/perfetto/metrics/android/powrails_metric.proto
index fcf0aa7..a17d47c 100644
--- a/protos/perfetto/metrics/android/powrails_metric.proto
+++ b/protos/perfetto/metrics/android/powrails_metric.proto
@@ -32,6 +32,9 @@
optional string name = 1;
// Energy data for given rail and for all samples in the trace.
repeated EnergyData energy_data = 2;
+ // The average used power between the first and the last sampled
+ // energy data in miliwatt (mw)
+ optional double avg_used_power_mw = 3;
}
// Energy data per Power Rail.
diff --git a/protos/perfetto/metrics/android/profiler_smaps.proto b/protos/perfetto/metrics/android/profiler_smaps.proto
new file mode 100644
index 0000000..bfb1416
--- /dev/null
+++ b/protos/perfetto/metrics/android/profiler_smaps.proto
@@ -0,0 +1,36 @@
+/*
+ * 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/android/process_metadata.proto";
+
+message ProfilerSmaps {
+ message Mapping {
+ optional string path = 1;
+ optional int32 size_kb = 2;
+ optional int32 private_dirty_kb = 3;
+ optional int32 swap_kb = 4;
+ }
+
+ message Instance {
+ optional AndroidProcessMetadata process = 1;
+ repeated Mapping mappings = 2;
+ }
+
+ repeated Instance instance = 1;
+}
diff --git a/protos/perfetto/metrics/android/startup_metric.proto b/protos/perfetto/metrics/android/startup_metric.proto
index 54bf1d7..aef7c10 100644
--- a/protos/perfetto/metrics/android/startup_metric.proto
+++ b/protos/perfetto/metrics/android/startup_metric.proto
@@ -131,6 +131,17 @@
message BinderTransaction {
optional Slice duration = 1;
optional string thread = 2;
+ optional string destination_thread = 3;
+ optional string destination_process = 4;
+ // From
+ // https://cs.android.com/android/platform/superproject/+/master:external/perfetto/protos/perfetto/trace/ftrace/binder.proto;l=15;drc=7b6a788162a30802f4c9d8d7a30a54e25edd30f1
+ optional string flags = 5;
+ // From
+ // https://cs.android.com/android/platform/superproject/+/master:external/perfetto/protos/perfetto/trace/ftrace/binder.proto;l=14;drc=7b6a788162a30802f4c9d8d7a30a54e25edd30f1
+ optional string code = 6;
+ // From
+ // https://cs.android.com/android/platform/superproject/+/master:external/perfetto/protos/perfetto/trace/ftrace/binder.proto;l=37;drc=7b6a788162a30802f4c9d8d7a30a54e25edd30f1
+ optional int64 data_size = 7;
}
// Metrics with information about the status of odex files and the outcome
diff --git a/protos/perfetto/metrics/android/surfaceflinger.proto b/protos/perfetto/metrics/android/surfaceflinger.proto
index 76fb493..3cc2c9e 100644
--- a/protos/perfetto/metrics/android/surfaceflinger.proto
+++ b/protos/perfetto/metrics/android/surfaceflinger.proto
@@ -39,4 +39,19 @@
// Calculate the number of missed GPU frames divided by
// total GPU frames
optional double missed_gpu_frame_rate = 6;
+
+ // Count the number of times SurfaceFlinger needs to invoke GPU
+ // for rendering some layers
+ optional uint32 gpu_invocations = 7;
+
+ // Calculate the average duration of GPU request by SurfaceFlinger
+ // since it enters the FenceMonitor's queue until it gets completed
+ optional double avg_gpu_waiting_dur_ms = 8;
+
+ // Calculate the total duration when there is at least one GPU request
+ // by SurfaceFlinger that is still waiting for GPU to complete the
+ // request.
+ // This also equals to the total duration of
+ // "waiting for GPU completion <fence_num>" in SurfaceFlinger.
+ optional double total_non_empty_gpu_waiting_dur_ms = 9;
}
diff --git a/protos/perfetto/metrics/android/trace_quality.proto b/protos/perfetto/metrics/android/trace_quality.proto
new file mode 100644
index 0000000..9d38444
--- /dev/null
+++ b/protos/perfetto/metrics/android/trace_quality.proto
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+// Metric which checks the data in the trace processor tables is "reasonble"
+// (i.e. we would expect to see it from a real device).
+//
+// This is useful to reject traces which may be valid (so no stat would be
+// recorded) but a human would find the trace nonsensical.
+message AndroidTraceQualityMetric {
+ message Failure {
+ // The name of the failed check.
+ optional string name = 1;
+ }
+ repeated Failure failures = 1;
+}
\ No newline at end of file
diff --git a/protos/perfetto/metrics/chrome/BUILD.gn b/protos/perfetto/metrics/chrome/BUILD.gn
index 0789138..ce0c908 100644
--- a/protos/perfetto/metrics/chrome/BUILD.gn
+++ b/protos/perfetto/metrics/chrome/BUILD.gn
@@ -28,6 +28,7 @@
"reported_by_page.proto",
"scroll_jank.proto",
"test_chrome_metric.proto",
+ "touch_jank.proto",
]
}
diff --git a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
index eb52099..1f21764 100644
--- a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
+++ b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
@@ -22,9 +22,10 @@
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/reported_by_page.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";
+import "protos/perfetto/metrics/chrome/touch_jank.proto";
extend TraceMetrics {
optional TestChromeMetric test_chrome_metric = 1001;
@@ -33,4 +34,5 @@
optional ScrollJank scroll_jank = 1004;
optional BlinkGcMetric blink_gc_metric = 1005;
optional MediaMetric media_metric = 1006;
+ optional TouchJank touch_jank = 1007;
}
diff --git a/protos/perfetto/metrics/chrome/touch_jank.proto b/protos/perfetto/metrics/chrome/touch_jank.proto
new file mode 100644
index 0000000..beebfb5
--- /dev/null
+++ b/protos/perfetto/metrics/chrome/touch_jank.proto
@@ -0,0 +1,34 @@
+/*
+ * 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 TouchJank {
+ // The percentage of time we consider janky of the total time spent performing
+ // touch gestures during the trace. I.E. approximately equal to
+ // |touch_jank_ms|/|touch_ms|.
+ optional double touch_jank_percentage = 1 [(unit) = "n%_smallerIsBetter"];
+ optional double touch_ms = 2 [(unit) = "ms_biggerIsBetter"];
+ optional double touch_processing_ms = 3 [(unit) = "ms_biggerIsBetter"];
+ optional double touch_jank_processing_ms = 4 [(unit) = "ms_smallerIsBetter"];
+ optional int64 num_touch_update_count = 5 [(unit) = "count_biggerIsBetter"];
+ optional int64 num_touch_update_jank_count = 6
+ [(unit) = "count_smallerIsBetter"];
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 164377f..5f2c801 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -35,13 +35,16 @@
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/multiuser_metric.proto";
import "protos/perfetto/metrics/android/package_list.proto";
import "protos/perfetto/metrics/android/powrails_metric.proto";
+import "protos/perfetto/metrics/android/profiler_smaps.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/task_names.proto";
import "protos/perfetto/metrics/android/thread_time_in_state_metric.proto";
+import "protos/perfetto/metrics/android/trace_quality.proto";
import "protos/perfetto/metrics/android/unsymbolized_frames.proto";
// Trace processor metadata
@@ -88,7 +91,7 @@
// Root message for all Perfetto-based metrics.
//
-// Next id: 34
+// Next id: 37
message TraceMetrics {
reserved 4, 10, 13, 14, 16, 19;
@@ -172,6 +175,15 @@
// Dmabuf heap metrics.
optional AndroidDmaHeapMetric android_dma_heap = 32;
+ // Metric to verify the quality of the trace.
+ optional AndroidTraceQualityMetric android_trace_quality = 34;
+
+ // Profiler smaps
+ optional ProfilerSmaps profiler_smaps = 35;
+
+ // Multiuser - metrics for switching users.
+ optional AndroidMultiuserMetric android_multiuser = 36;
+
// Demo extensions.
extensions 450 to 499;
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index dc2196e..15a119f 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -200,25 +200,32 @@
// 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;
+
+ optional double max_dur_ms = 7;
+ optional double min_dur_ms = 8;
+ optional double avg_dur_ms = 9;
+
+ // Removed: was int64 versions of max_dur_ns, min_dur_ns and avg_dur_ns.
+ reserved 2 to 4;
}
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;
+
+ // max/min/avg G2d frame durations for all instances.
+ optional double max_dur_ms = 7;
+ optional double min_dur_ms = 8;
+ optional double avg_dur_ms = 9;
+
+ // Removed: was int64 versions of max_dur_ns, min_dur_ns and avg_dur_ns.
+ reserved 2 to 4;
}
optional G2dMetric g2d_hw = 1;
@@ -247,6 +254,35 @@
optional int64 mem_max = 2;
optional int64 mem_min = 3;
optional int64 mem_avg = 4;
+
+ message FrequencyMetric {
+ // Identifier for GPU in a multi-gpu device.
+ optional uint32 gpu_id = 1;
+
+ // max/min/avg GPU frequency for this gpu_id
+ // the calculation of avg is weighted by the duration of each frequency
+ optional int64 freq_max = 2;
+ optional int64 freq_min = 3;
+ optional double freq_avg = 4;
+
+ message MetricsPerFrequency {
+ // Used frequency
+ optional int64 freq = 1;
+
+ // Total duration in ms when the state of GPU was in this frequency
+ optional double dur_ms = 2;
+
+ // Percentage of duration in this frequency compared to all frequencies
+ // in this gpu_id
+ optional double percentage = 3;
+ }
+
+ // Metrics for each used GPU frequency
+ repeated MetricsPerFrequency used_freqs = 5;
+ }
+
+ // GPU frequency metric for each gpu_id
+ repeated FrequencyMetric freq_metrics = 5;
}
// End of protos/perfetto/metrics/android/gpu_metric.proto
@@ -294,6 +330,26 @@
// the average of hwcomposer execution time for separated validation cases.
optional double avg_separated_execution_time_ms = 13;
+
+ message DpuVoteMetrics {
+ // the thread ID that handles this track
+ optional uint32 tid = 1;
+
+ // the weighted average of DPU Vote Clock
+ optional double avg_dpu_vote_clock = 2;
+
+ // the weighted average of DPU Vote Avg Bandwidth
+ optional double avg_dpu_vote_avg_bw = 3;
+
+ // the weighted average of DPU Vote Peak Bandwidth
+ optional double avg_dpu_vote_peak_bw = 4;
+
+ // the weighted average of DPU Vote RT (Real Time) Bandwidth
+ optional double avg_dpu_vote_rt_bw = 5;
+ }
+
+ // DPU Vote Metrics for each thread track
+ repeated DpuVoteMetrics dpu_vote_metrics = 14;
}
// End of protos/perfetto/metrics/android/hwcomposer.proto
@@ -646,6 +702,35 @@
// End of protos/perfetto/metrics/android/mem_unagg_metric.proto
+// Begin of protos/perfetto/metrics/android/multiuser_metric.proto
+
+// Metrics for Multiuser events, such as switching users.
+message AndroidMultiuserMetric {
+
+ // Holds the data for a Multiuser event.
+ message EventData {
+ // Duration of the event (in milliseconds).
+ optional int32 duration_ms = 1;
+
+ // CPU usage of each process during the event.
+ message CpuUsage {
+ // The userId of the process (e.g. 0 or 10).
+ optional int32 user_id = 1;
+ // The name of the process.
+ optional string process_name = 2;
+ // The number of CPU cycles (in megacycles) spent by that process during the event.
+ optional int32 cpu_mcycles = 3;
+ // The ratio of this process's cycles to the total for all processes, expressed as a percentage.
+ optional float cpu_percentage = 4;
+ }
+ repeated CpuUsage cpu_usage = 2;
+ }
+
+ // Metrics for a user switch.
+ optional EventData user_switch = 1;
+}
+// End of protos/perfetto/metrics/android/multiuser_metric.proto
+
// Begin of protos/perfetto/metrics/android/package_list.proto
message AndroidPackageList {
@@ -676,6 +761,9 @@
optional string name = 1;
// Energy data for given rail and for all samples in the trace.
repeated EnergyData energy_data = 2;
+ // The average used power between the first and the last sampled
+ // energy data in miliwatt (mw)
+ optional double avg_used_power_mw = 3;
}
// Energy data per Power Rail.
@@ -683,6 +771,26 @@
}
// End of protos/perfetto/metrics/android/powrails_metric.proto
+// Begin of protos/perfetto/metrics/android/profiler_smaps.proto
+
+message ProfilerSmaps {
+ message Mapping {
+ optional string path = 1;
+ optional int32 size_kb = 2;
+ optional int32 private_dirty_kb = 3;
+ optional int32 swap_kb = 4;
+ }
+
+ message Instance {
+ optional AndroidProcessMetadata process = 1;
+ repeated Mapping mappings = 2;
+ }
+
+ repeated Instance instance = 1;
+}
+
+// End of protos/perfetto/metrics/android/profiler_smaps.proto
+
// Begin of protos/perfetto/metrics/android/startup_metric.proto
// Android app startup metrics.
@@ -796,6 +904,17 @@
message BinderTransaction {
optional Slice duration = 1;
optional string thread = 2;
+ optional string destination_thread = 3;
+ optional string destination_process = 4;
+ // From
+ // https://cs.android.com/android/platform/superproject/+/master:external/perfetto/protos/perfetto/trace/ftrace/binder.proto;l=15;drc=7b6a788162a30802f4c9d8d7a30a54e25edd30f1
+ optional string flags = 5;
+ // From
+ // https://cs.android.com/android/platform/superproject/+/master:external/perfetto/protos/perfetto/trace/ftrace/binder.proto;l=14;drc=7b6a788162a30802f4c9d8d7a30a54e25edd30f1
+ optional string code = 6;
+ // From
+ // https://cs.android.com/android/platform/superproject/+/master:external/perfetto/protos/perfetto/trace/ftrace/binder.proto;l=37;drc=7b6a788162a30802f4c9d8d7a30a54e25edd30f1
+ optional int64 data_size = 7;
}
// Metrics with information about the status of odex files and the outcome
@@ -898,6 +1017,21 @@
// Calculate the number of missed GPU frames divided by
// total GPU frames
optional double missed_gpu_frame_rate = 6;
+
+ // Count the number of times SurfaceFlinger needs to invoke GPU
+ // for rendering some layers
+ optional uint32 gpu_invocations = 7;
+
+ // Calculate the average duration of GPU request by SurfaceFlinger
+ // since it enters the FenceMonitor's queue until it gets completed
+ optional double avg_gpu_waiting_dur_ms = 8;
+
+ // Calculate the total duration when there is at least one GPU request
+ // by SurfaceFlinger that is still waiting for GPU to complete the
+ // request.
+ // This also equals to the total duration of
+ // "waiting for GPU completion <fence_num>" in SurfaceFlinger.
+ optional double total_non_empty_gpu_waiting_dur_ms = 9;
}
// End of protos/perfetto/metrics/android/surfaceflinger.proto
@@ -987,6 +1121,22 @@
// End of protos/perfetto/metrics/android/thread_time_in_state_metric.proto
+// Begin of protos/perfetto/metrics/android/trace_quality.proto
+
+// Metric which checks the data in the trace processor tables is "reasonble"
+// (i.e. we would expect to see it from a real device).
+//
+// This is useful to reject traces which may be valid (so no stat would be
+// recorded) but a human would find the trace nonsensical.
+message AndroidTraceQualityMetric {
+ message Failure {
+ // The name of the failed check.
+ optional string name = 1;
+ }
+ repeated Failure failures = 1;
+}
+// End of protos/perfetto/metrics/android/trace_quality.proto
+
// Begin of protos/perfetto/metrics/android/unsymbolized_frames.proto
message UnsymbolizedFrames {
@@ -1047,7 +1197,7 @@
// Root message for all Perfetto-based metrics.
//
-// Next id: 34
+// Next id: 37
message TraceMetrics {
reserved 4, 10, 13, 14, 16, 19;
@@ -1131,6 +1281,15 @@
// Dmabuf heap metrics.
optional AndroidDmaHeapMetric android_dma_heap = 32;
+ // Metric to verify the quality of the trace.
+ optional AndroidTraceQualityMetric android_trace_quality = 34;
+
+ // Profiler smaps
+ optional ProfilerSmaps profiler_smaps = 35;
+
+ // Multiuser - metrics for switching users.
+ optional AndroidMultiuserMetric android_multiuser = 36;
+
// Demo extensions.
extensions 450 to 499;
diff --git a/protos/perfetto/trace/ftrace/cgroup.proto b/protos/perfetto/trace/ftrace/cgroup.proto
index b8a7d1e..efa8b9e 100644
--- a/protos/perfetto/trace/ftrace/cgroup.proto
+++ b/protos/perfetto/trace/ftrace/cgroup.proto
@@ -11,6 +11,8 @@
optional int32 pid = 3;
optional string comm = 4;
optional string cname = 5;
+ optional int32 dst_level = 6;
+ optional string dst_path = 7;
}
message CgroupMkdirFtraceEvent {
optional int32 root = 1;
diff --git a/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto b/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
index 69aedaa..fc88748 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
@@ -26,6 +26,7 @@
message FtraceEventBundle {
optional uint32 cpu = 1;
repeated FtraceEvent event = 2;
+
// Set to true if there was data loss between the last time we've read from
// the corresponding per-cpu kernel buffer, and the earliest event recorded
// in this bundle.
@@ -62,4 +63,27 @@
repeated uint32 waking_comm_index = 11 [packed = true];
}
optional CompactSched compact_sched = 4;
+
+ // traced_probes always sets the ftrace_clock to "boot". That is not available
+ // in older kernels (v3.x). In that case we fallback on "global" or "local".
+ // When we do that, we report the fallback clock in each bundle so we can do
+ // proper clock syncing at parsing time in TraceProcessor. We cannot use the
+ // TracePacket timestamp_clock_id because: (1) there is no per-packet
+ // timestamp for ftrace bundles; (2) technically we cannot be guaranteed that
+ // "global" matches CLOCK_MONOTONIC (although it seems to do so in practice).
+ // Having a dedicated and explicit flag allows us to correct further misakes
+ // in future by looking at the kernel version.
+ // This field has been introduced in perfetto v19 / Android T (13).
+ // This field is omitted when the ftrace clock is just "boot", as that is the
+ // default assumption (and for consistency with the past).
+ optional FtraceClock ftrace_clock = 5;
}
+
+enum FtraceClock {
+ // There is no FTRACE_CLOCK_BOOT entry as that's the default assumption. When
+ // the ftrace clock is "boot", it's just omitted (so UNSPECIFIED == BOOT).
+ FTRACE_CLOCK_UNSPECIFIED = 0;
+ FTRACE_CLOCK_UNKNOWN = 1;
+ FTRACE_CLOCK_GLOBAL = 2;
+ FTRACE_CLOCK_LOCAL = 3;
+}
\ No newline at end of file
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 4ee4df6..b8f69c5 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -833,7 +833,13 @@
oneof event {
Counter counter = 4;
Tracepoint tracepoint = 3;
+ RawEvent raw_event = 5;
}
+
+ // Optional arbitrary name for the event, to identify it in the parsed
+ // trace. Does *not* affect the profiling itself. If unset, the trace
+ // parser will choose a suitable name.
+ optional string name = 10;
}
enum Counter {
@@ -859,6 +865,16 @@
// https://www.kernel.org/doc/Documentation/trace/events.txt
optional string filter = 2;
}
+
+ // Syscall-level description of the event, propagated to the perf_event_attr
+ // struct. Primarily for local use-cases, since the event availability and
+ // encoding is hardware-specific.
+ message RawEvent {
+ optional uint32 type = 1;
+ optional uint64 config = 2;
+ optional uint64 config1 = 3;
+ optional uint64 config2 = 4;
+ }
}
// End of protos/perfetto/common/perf_events.proto
@@ -939,6 +955,14 @@
// If unset, the cached state will not be cleared.
optional uint32 unwind_state_clear_period_ms = 10;
+ // If set, only profile target if it was installed by a package with one of
+ // these names. Special values:
+ // * "@system": installed on the system partition
+ // * "@product": installed on the product partition
+ // * "@null": sideloaded
+ // Supported on Android 12+.
+ repeated string target_installed_by = 18;
+
//
// Deprecated (superseded by options above):
//
@@ -952,14 +976,6 @@
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;
@@ -1474,7 +1490,7 @@
// 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: 34.
message TraceConfig {
message BufferConfig {
optional uint32 size_kb = 1;
@@ -1874,10 +1890,17 @@
// 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;
+ // `-T filter_out.escaped_string` (for .pbtx). See go/trace-filtering for
+ // design.
+ //
+ // Introduced in Android S, but it was broken (b/195065199). Reintroduced in
+ // Android T with a different field number.
+ message TraceFilter {
+ optional bytes bytecode = 1;
+ }
+ // old field number for trace_filter
+ reserved 32;
+ optional TraceFilter trace_filter = 33;
}
// End of protos/perfetto/config/trace_config.proto
@@ -3038,6 +3061,8 @@
optional int32 pid = 3;
optional string comm = 4;
optional string cname = 5;
+ optional int32 dst_level = 6;
+ optional string dst_path = 7;
}
message CgroupMkdirFtraceEvent {
optional int32 root = 1;
@@ -5563,6 +5588,7 @@
message FtraceEventBundle {
optional uint32 cpu = 1;
repeated FtraceEvent event = 2;
+
// Set to true if there was data loss between the last time we've read from
// the corresponding per-cpu kernel buffer, and the earliest event recorded
// in this bundle.
@@ -5599,8 +5625,30 @@
repeated uint32 waking_comm_index = 11 [packed = true];
}
optional CompactSched compact_sched = 4;
+
+ // traced_probes always sets the ftrace_clock to "boot". That is not available
+ // in older kernels (v3.x). In that case we fallback on "global" or "local".
+ // When we do that, we report the fallback clock in each bundle so we can do
+ // proper clock syncing at parsing time in TraceProcessor. We cannot use the
+ // TracePacket timestamp_clock_id because: (1) there is no per-packet
+ // timestamp for ftrace bundles; (2) technically we cannot be guaranteed that
+ // "global" matches CLOCK_MONOTONIC (although it seems to do so in practice).
+ // Having a dedicated and explicit flag allows us to correct further misakes
+ // in future by looking at the kernel version.
+ // This field has been introduced in perfetto v19 / Android T (13).
+ // This field is omitted when the ftrace clock is just "boot", as that is the
+ // default assumption (and for consistency with the past).
+ optional FtraceClock ftrace_clock = 5;
}
+enum FtraceClock {
+ // There is no FTRACE_CLOCK_BOOT entry as that's the default assumption. When
+ // the ftrace clock is "boot", it's just omitted (so UNSPECIFIED == BOOT).
+ FTRACE_CLOCK_UNSPECIFIED = 0;
+ FTRACE_CLOCK_UNKNOWN = 1;
+ FTRACE_CLOCK_GLOBAL = 2;
+ FTRACE_CLOCK_LOCAL = 3;
+}
// End of protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
// Begin of protos/perfetto/trace/ftrace/ftrace_stats.proto
@@ -6301,7 +6349,8 @@
// The original format was generated in JSON by the code at
// https://cs.chromium.org/chromium/src/cc/scheduler/scheduler.cc?l=870&rcl=5e15eabc9c0eec8daf94fdf78e93f13b6e3b63dd
//
-// TODO(nuskos): Update link once we've switched to writing this proto.
+// And is now generated as protozero:
+// https://cs.chromium.org/chromium/src/cc/scheduler/scheduler.cc?q=Scheduler::AsPro
//
// All non-delta-timestamps are absolute CLOCK_MONOTONIC timestamps.
@@ -6337,7 +6386,6 @@
optional bool begin_impl_frame_deadline_task = 3;
optional bool pending_begin_frame_task = 4;
optional bool skipped_last_frame_missed_exceeded_deadline = 5;
- optional bool skipped_last_frame_to_reduce_latency = 6;
optional ChromeCompositorSchedulerAction inside_action = 7;
optional BeginImplFrameDeadlineMode deadline_mode = 8;
optional int64 deadline_us = 9;
@@ -6349,6 +6397,8 @@
optional BeginFrameObserverState begin_frame_observer_state = 15;
optional BeginFrameSourceState begin_frame_source_state = 16;
optional CompositorTimingHistory compositor_timing_history = 17;
+
+ reserved 6;
}
// Describes the current values stored in the Chrome Compositor state machine.
@@ -6438,7 +6488,6 @@
optional ScrollHandlerState scroll_handler_state = 32;
optional bool critical_begin_main_frame_to_activate_is_fast = 33;
optional bool main_thread_missed_last_deadline = 34;
- optional bool skip_next_begin_main_frame_to_reduce_latency = 35;
optional bool video_needs_begin_frames = 36;
optional bool defer_begin_main_frame = 37;
optional bool last_commit_had_no_updates = 38;
@@ -6450,11 +6499,13 @@
optional bool processing_animation_worklets_for_active_tree = 44;
optional bool processing_animation_worklets_for_pending_tree = 45;
optional bool processing_paint_worklets_for_pending_tree = 46;
+
+ reserved 35;
}
optional MinorState minor_state = 2;
}
-// Next id: 12
+// Next id: 13
message BeginFrameArgs {
// JSON format has a "type" field that was always just "BeginFrameArgs" we
// drop this in the proto representation, and instead make the JSON format
@@ -6483,6 +6534,7 @@
// remove this |source_location|.
SourceLocation source_location = 10;
}
+ optional int64 frames_throttled_since_last = 12;
}
// Next id: 7
@@ -6606,11 +6658,11 @@
SCROLL_MAIN_THREAD = 1;
SCROLL_COMPOSITOR_THREAD = 2;
- // Used when it can't be determined wheter a scroll is in progress or not.
+ // Used when it can't be determined whether a scroll is in progress or not.
SCROLL_UNKNOWN = 3;
}
- // The type of active scroll
+ // The type of active scroll.
optional ScrollState scroll_state = 6;
// If any main thread animation is active during this frame.
@@ -6709,6 +6761,7 @@
repeated ComponentInfo component_info = 4;
optional bool is_coalesced = 5;
optional int64 gesture_scroll_id = 6;
+ optional int64 touch_id = 7;
}
// End of protos/perfetto/trace/track_event/chrome_latency_info.proto
@@ -7796,6 +7849,58 @@
// Begin of protos/perfetto/trace/profiling/profile_packet.proto
+// This file contains a mixture of messages emitted by various sampling
+// profilers:
+//
+// Memory allocator profiling
+// ----------------
+// ProfilePacket:
+// The packet emitted by heapprofd, which started off as a native heap
+// (malloc/free) profiler, but now supports custom allocators as well. Each
+// packet contains a preaggregated state of the heap at snapshot time, which
+// report the total allocated/free bytes per callstack (plus other info such
+// as the number of samples).
+// StreamingAllocation/StreamingFree:
+// Emitted by heapprofd when configured in streaming mode (i.e. when
+// stream_allocations = true). This is only for local testing, and doesn't
+// report callstacks (only address time and size of each alloc/free). It can
+// lead to enormous traces, as it contains the stream of each alloc/free call.
+//
+// Callstack sampling
+// ------------------
+// StreamingProfilePacket:
+// The packet emitted by the chromium in-process sampling profiler, which is
+// based on periodically sending a signal to itself, and unwinding the stack
+// in the signal handler. Each packet contains a series of individual stack
+// samples for a Chromium thread.
+//
+// Callstack and performance counter sampling
+// ---------------------
+// PerfSample:
+// The packet emitted by traced_perf sampling performance profiler based on
+// the perf_event_open syscall. Each packet represents an individual sample
+// of a performance counter (which might be a timer), and optionally a
+// callstack of the process that was scheduled at the time of the sample.
+//
+
+// The packet emitted by heapprofd for each heap snapshot. A snapshot can
+// involve more than one ProfilePacket if the snapshot is big (when |continued|
+// is true). The cardinality and grouping is as follows:
+// A ProfilePacket contains:
+// - 1+ per-process heap snapshots (ProcessHeapSamples). Normally there is only
+// one heap per process (the main malloc/free heap), but there can be more if
+// the process is using the heapprofd API to profile custom allocators.
+// - Globally interned strings, mappings and frames (to allow de-duplicating
+// frames/mapping in common between different processes).
+// A ProcessHeapSamples contains:
+// - The process and heap identifier.
+// - A number of HeapSample, one for each callsite that had some alloc/frees.
+// - Statistics about heapprofd internals (e.g., sampling/unwinding timings).
+// A HeapSample contains statistics about callsites:
+// - Total number of bytes allocated and freed from that callsite.
+// - Total number of alloc/free calls sampled.
+// - Stats at the local maximum when dump_at_max = true.
+// See https://perfetto.dev/docs/data-sources/native-heap-profiler for more.
message ProfilePacket {
// The following interning tables are only used in Android version Q.
// In newer versions, these tables are in InternedData
@@ -7934,6 +8039,8 @@
optional uint64 index = 7;
}
+// Packet emitted by heapprofd when stream_allocations = true. Only for local
+// testing. Doesn't report the callsite.
message StreamingAllocation {
// TODO(fmayer): Add callstack.
repeated uint64 address = 1;
@@ -7944,6 +8051,8 @@
repeated uint64 sequence_number = 6;
};
+// Packet emitted by heapprofd when stream_allocations = true. Only for local
+// testing. Doesn't report the callsite.
message StreamingFree {
// TODO(fmayer): Add callstack.
repeated uint64 address = 1;
@@ -7951,8 +8060,9 @@
repeated uint64 sequence_number = 3;
};
-// Message used to represent individual stack samples sampled at discrete
-// points in time, rather than aggregated over an interval.
+// Packet emitted by the chromium in-process signal-based callstack sampler.
+// Represents a series of 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;
@@ -7992,18 +8102,20 @@
}
}
-// Individual performance sampling packet payload. Typically corresponds to a
-// stack sample on a configration-dependent counter overflow.
+// Packet emitted by the traced_perf sampling performance profiler, which
+// gathers data via the perf_event_open syscall. Each packet contains an
+// individual sample with a counter value, and optionally a
+// callstack.
//
// 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:
-// * 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)
+// * normal sample (timebase_count set, typically also callstack_iid)
message PerfSample {
optional uint32 cpu = 1;
optional uint32 pid = 2;
@@ -8068,6 +8180,7 @@
// 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
diff --git a/protos/perfetto/trace/profiling/profile_packet.proto b/protos/perfetto/trace/profiling/profile_packet.proto
index 8548a4e..8b147fa 100644
--- a/protos/perfetto/trace/profiling/profile_packet.proto
+++ b/protos/perfetto/trace/profiling/profile_packet.proto
@@ -21,6 +21,58 @@
package perfetto.protos;
+// This file contains a mixture of messages emitted by various sampling
+// profilers:
+//
+// Memory allocator profiling
+// ----------------
+// ProfilePacket:
+// The packet emitted by heapprofd, which started off as a native heap
+// (malloc/free) profiler, but now supports custom allocators as well. Each
+// packet contains a preaggregated state of the heap at snapshot time, which
+// report the total allocated/free bytes per callstack (plus other info such
+// as the number of samples).
+// StreamingAllocation/StreamingFree:
+// Emitted by heapprofd when configured in streaming mode (i.e. when
+// stream_allocations = true). This is only for local testing, and doesn't
+// report callstacks (only address time and size of each alloc/free). It can
+// lead to enormous traces, as it contains the stream of each alloc/free call.
+//
+// Callstack sampling
+// ------------------
+// StreamingProfilePacket:
+// The packet emitted by the chromium in-process sampling profiler, which is
+// based on periodically sending a signal to itself, and unwinding the stack
+// in the signal handler. Each packet contains a series of individual stack
+// samples for a Chromium thread.
+//
+// Callstack and performance counter sampling
+// ---------------------
+// PerfSample:
+// The packet emitted by traced_perf sampling performance profiler based on
+// the perf_event_open syscall. Each packet represents an individual sample
+// of a performance counter (which might be a timer), and optionally a
+// callstack of the process that was scheduled at the time of the sample.
+//
+
+// The packet emitted by heapprofd for each heap snapshot. A snapshot can
+// involve more than one ProfilePacket if the snapshot is big (when |continued|
+// is true). The cardinality and grouping is as follows:
+// A ProfilePacket contains:
+// - 1+ per-process heap snapshots (ProcessHeapSamples). Normally there is only
+// one heap per process (the main malloc/free heap), but there can be more if
+// the process is using the heapprofd API to profile custom allocators.
+// - Globally interned strings, mappings and frames (to allow de-duplicating
+// frames/mapping in common between different processes).
+// A ProcessHeapSamples contains:
+// - The process and heap identifier.
+// - A number of HeapSample, one for each callsite that had some alloc/frees.
+// - Statistics about heapprofd internals (e.g., sampling/unwinding timings).
+// A HeapSample contains statistics about callsites:
+// - Total number of bytes allocated and freed from that callsite.
+// - Total number of alloc/free calls sampled.
+// - Stats at the local maximum when dump_at_max = true.
+// See https://perfetto.dev/docs/data-sources/native-heap-profiler for more.
message ProfilePacket {
// The following interning tables are only used in Android version Q.
// In newer versions, these tables are in InternedData
@@ -159,6 +211,8 @@
optional uint64 index = 7;
}
+// Packet emitted by heapprofd when stream_allocations = true. Only for local
+// testing. Doesn't report the callsite.
message StreamingAllocation {
// TODO(fmayer): Add callstack.
repeated uint64 address = 1;
@@ -169,6 +223,8 @@
repeated uint64 sequence_number = 6;
};
+// Packet emitted by heapprofd when stream_allocations = true. Only for local
+// testing. Doesn't report the callsite.
message StreamingFree {
// TODO(fmayer): Add callstack.
repeated uint64 address = 1;
@@ -176,8 +232,9 @@
repeated uint64 sequence_number = 3;
};
-// Message used to represent individual stack samples sampled at discrete
-// points in time, rather than aggregated over an interval.
+// Packet emitted by the chromium in-process signal-based callstack sampler.
+// Represents a series of 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;
@@ -217,18 +274,20 @@
}
}
-// Individual performance sampling packet payload. Typically corresponds to a
-// stack sample on a configration-dependent counter overflow.
+// Packet emitted by the traced_perf sampling performance profiler, which
+// gathers data via the perf_event_open syscall. Each packet contains an
+// individual sample with a counter value, and optionally a
+// callstack.
//
// 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:
-// * 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)
+// * normal sample (timebase_count set, typically also callstack_iid)
message PerfSample {
optional uint32 cpu = 1;
optional uint32 pid = 2;
@@ -292,4 +351,4 @@
// 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/track_event/chrome_compositor_scheduler_state.proto b/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
index 109180a..476ed38 100644
--- a/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
+++ b/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
@@ -31,7 +31,8 @@
// The original format was generated in JSON by the code at
// https://cs.chromium.org/chromium/src/cc/scheduler/scheduler.cc?l=870&rcl=5e15eabc9c0eec8daf94fdf78e93f13b6e3b63dd
//
-// TODO(nuskos): Update link once we've switched to writing this proto.
+// And is now generated as protozero:
+// https://cs.chromium.org/chromium/src/cc/scheduler/scheduler.cc?q=Scheduler::AsPro
//
// All non-delta-timestamps are absolute CLOCK_MONOTONIC timestamps.
@@ -67,7 +68,6 @@
optional bool begin_impl_frame_deadline_task = 3;
optional bool pending_begin_frame_task = 4;
optional bool skipped_last_frame_missed_exceeded_deadline = 5;
- optional bool skipped_last_frame_to_reduce_latency = 6;
optional ChromeCompositorSchedulerAction inside_action = 7;
optional BeginImplFrameDeadlineMode deadline_mode = 8;
optional int64 deadline_us = 9;
@@ -79,6 +79,8 @@
optional BeginFrameObserverState begin_frame_observer_state = 15;
optional BeginFrameSourceState begin_frame_source_state = 16;
optional CompositorTimingHistory compositor_timing_history = 17;
+
+ reserved 6;
}
// Describes the current values stored in the Chrome Compositor state machine.
@@ -168,7 +170,6 @@
optional ScrollHandlerState scroll_handler_state = 32;
optional bool critical_begin_main_frame_to_activate_is_fast = 33;
optional bool main_thread_missed_last_deadline = 34;
- optional bool skip_next_begin_main_frame_to_reduce_latency = 35;
optional bool video_needs_begin_frames = 36;
optional bool defer_begin_main_frame = 37;
optional bool last_commit_had_no_updates = 38;
@@ -180,11 +181,13 @@
optional bool processing_animation_worklets_for_active_tree = 44;
optional bool processing_animation_worklets_for_pending_tree = 45;
optional bool processing_paint_worklets_for_pending_tree = 46;
+
+ reserved 35;
}
optional MinorState minor_state = 2;
}
-// Next id: 12
+// Next id: 13
message BeginFrameArgs {
// JSON format has a "type" field that was always just "BeginFrameArgs" we
// drop this in the proto representation, and instead make the JSON format
@@ -213,6 +216,7 @@
// remove this |source_location|.
SourceLocation source_location = 10;
}
+ optional int64 frames_throttled_since_last = 12;
}
// Next id: 7
diff --git a/protos/perfetto/trace/track_event/chrome_frame_reporter.proto b/protos/perfetto/trace/track_event/chrome_frame_reporter.proto
index 00930c7..f1165a8 100644
--- a/protos/perfetto/trace/track_event/chrome_frame_reporter.proto
+++ b/protos/perfetto/trace/track_event/chrome_frame_reporter.proto
@@ -74,11 +74,11 @@
SCROLL_MAIN_THREAD = 1;
SCROLL_COMPOSITOR_THREAD = 2;
- // Used when it can't be determined wheter a scroll is in progress or not.
+ // Used when it can't be determined whether a scroll is in progress or not.
SCROLL_UNKNOWN = 3;
}
- // The type of active scroll
+ // The type of active scroll.
optional ScrollState scroll_state = 6;
// If any main thread animation is active during this frame.
diff --git a/protos/perfetto/trace/track_event/chrome_latency_info.proto b/protos/perfetto/trace/track_event/chrome_latency_info.proto
index 5412b40..75113ea 100644
--- a/protos/perfetto/trace/track_event/chrome_latency_info.proto
+++ b/protos/perfetto/trace/track_event/chrome_latency_info.proto
@@ -84,4 +84,5 @@
repeated ComponentInfo component_info = 4;
optional bool is_coalesced = 5;
optional int64 gesture_scroll_id = 6;
+ optional int64 touch_id = 7;
}
diff --git a/protos/perfetto/trace_processor/trace_processor.proto b/protos/perfetto/trace_processor/trace_processor.proto
index fbff9d7..7fb2c33 100644
--- a/protos/perfetto/trace_processor/trace_processor.proto
+++ b/protos/perfetto/trace_processor/trace_processor.proto
@@ -41,7 +41,7 @@
// every time a new feature that the UI depends on is being introduced (e.g.
// new tables, new SQL operators, metrics that are required by the UI).
// See also TraceProcessorVersion (below).
- TRACE_PROCESSOR_CURRENT_API_VERSION = 1;
+ TRACE_PROCESSOR_CURRENT_API_VERSION = 2;
}
// At lowest level, the wire-format of the RPC procol is a linear sequence of
diff --git a/protos/third_party/chromium/BUILD.gn b/protos/third_party/chromium/BUILD.gn
index cff5b38..83228a6 100644
--- a/protos/third_party/chromium/BUILD.gn
+++ b/protos/third_party/chromium/BUILD.gn
@@ -2,6 +2,11 @@
import("../../../gn/proto_library.gni")
import("sources.gni")
+perfetto_proto_library("@TYPE@") {
+ sources = chrome_track_event_sources
+ deps = [ "../../perfetto/trace/track_event:@TYPE@" ]
+}
+
perfetto_proto_library("chrome_track_event_@TYPE@") {
proto_generators = [ "descriptor" ]
sources = chrome_track_event_sources
diff --git a/protos/third_party/chromium/chrome_track_event.proto b/protos/third_party/chromium/chrome_track_event.proto
index 54e11ce..1d832ff 100644
--- a/protos/third_party/chromium/chrome_track_event.proto
+++ b/protos/third_party/chromium/chrome_track_event.proto
@@ -34,7 +34,8 @@
}
message ChromeBrowserContext {
- optional fixed64 ptr = 1;
+ reserved 1;
+ optional string id = 2;
}
message ChromeProfileDestroyer {
@@ -95,8 +96,10 @@
optional uint64 frame_tree_node_id = 4;
}
+// Matches content::ShouldSwapBrowsingInstance.
enum ShouldSwapBrowsingInstance {
- // No BrowsingInstance swap.
+ // Was used for all "no BrowsingInstance swap" scenarios, now broken down in
+ // separate reasons.
SHOULD_SWAP_BROWSING_INSTANCE_NO = 0;
// Forced BrowsingInstance swap.
@@ -107,6 +110,26 @@
// Proactive BrowsingInstance swap for same-site navigation.
SHOULD_SWAP_BROWSING_INSTANCE_YES_SAME_SITE_PROACTIVE_SWAP = 3;
+
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_PROACTIVE_SWAP_DISABLED = 4;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_NOT_MAIN_FRAME = 5;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_HAS_RELATED_ACTIVE_CONTENTS = 6;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_DOES_NOT_HAVE_SITE = 7;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_SOURCE_URL_SCHEME_NOT_HTTP_OR_HTTPS = 8;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_DESTINATION_URL_SCHEME_NOT_HTTP_OR_HTTPS = 9;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_SAME_SITE_NAVIGATION = 10;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_RELOADING_ERROR_PAGE = 11;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_ALREADY_HAS_MATCHING_BROWSING_INSTANCE = 12;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_RENDERER_DEBUG_URL = 13;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_NOT_NEEDED_FOR_BACK_FORWARD_CACHE = 14;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_SAME_DOCUMENT_NAVIGATION = 15;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_SAME_URL_NAVIGATION = 16;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_WILL_REPLACE_ENTRY = 17;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_RELOAD = 18;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_GUEST = 19;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_HAS_NOT_COMMITTED_ANY_NAVIGATION = 20;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_UNLOAD_HANDLER_EXISTS_ON_SAME_SITE_NAVIGATION =
+ 21;
}
message ShouldSwapBrowsingInstancesResult {
@@ -133,6 +156,29 @@
optional string site = 2;
optional uint32 mark_hash = 3;
optional string mark = 4;
+
+ // A randomly generated unique identifier for a given ExecutionContext
+ // (document, worker, etc). Used to be able to correlate events in a process
+ // where there are multiple execution contexts from the same site.
+ optional uint32 execution_context_id = 5;
+
+ // Indicates the sequence number of this particular mark being emitted from
+ // a particular site in the scope of a single ExecutionContext. Typical
+ // sites emit batches of events that are correlated in time (a thing started,
+ // a thing reached a given milestone, a thing completed). When these events
+ // are intermixed it is useful to know which ones are semantically related.
+ // The value is generated by the content itself, but shifted by a fixed
+ // random offset at runtime so as to limit usage as a side channel.
+ optional uint32 sequence_number = 6;
+}
+
+message ChromeWebAppBadNavigate {
+ optional bool is_kiosk = 1;
+ optional bool has_hosted_app_controller = 2;
+ optional string app_name = 3;
+ optional uint32 system_app_type = 4;
+ optional bool web_app_provider_registry_ready = 5;
+ optional bool system_web_app_manager_synchronized = 6;
}
// These IDs are generated at compile time and differ for each chrome version.
@@ -142,9 +188,128 @@
optional uint32 resource_id = 1;
}
+// Information about RenderProcessHost.
+message RenderProcessHost {
+ // Unique Id to identify the RenderProcessHost. This is the browser-side,
+ // persistent id for this RenderProcessHost that stays constant even across OS
+ // layer processes managed by this RenderProcessHost.
+ optional uint32 id = 1;
+ // See ProcessLock::ToString().
+ optional string process_lock = 2;
+ // The PID of the child process.
+ optional int32 child_process_id = 3;
+
+ // Details about the associated browser context.
+ optional ChromeBrowserContext browser_context = 4;
+}
+
+message RenderProcessHostListener {
+ // Routing ID of the listener to the RenderProcessHost, recorded when a new ID
+ // is added or when an ID is removed.
+ optional uint32 routing_id = 1;
+}
+
+message RenderProcessHostCleanup {
+ // Number of IPC listeners registered to the host when Cleanup() was called.
+ optional uint32 listener_count = 1;
+ // Number of "keep alive" references active in the RenderProcessHost, recorded
+ // when Cleanup() was called.
+ optional uint32 keep_alive_ref_count = 2;
+ // Number of "shutdown delay" references active in the RenderProcessHost,
+ // recorded when Cleanup() was called.
+ optional uint32 shutdown_delay_ref_count = 3;
+ // Number of "worker delay" references active in the RenderProcessHost,
+ // recorded when Cleanup() was called.
+ optional uint32 worker_ref_count = 4;
+}
+
+message ChildProcessLauncherPriority {
+ // True if the new priority set to background.
+ optional bool is_backgrounded = 1;
+ // True if the renderer proecss has pending views.
+ optional bool has_pending_views = 2;
+
+ // Importance of the child process in Android.
+ enum Importance {
+ IMPORTANCE_NORMAL = 1;
+ IMPORTANCE_MODERATE = 2;
+ IMPORTANCE_IMPORTANT = 3;
+ }
+ optional Importance importance = 3;
+}
+
+// Information that identifies a Chrome Extension.
+message ChromeExtensionId {
+ // Unique id that identifies a Chrome Extension.
+ optional string extension_id = 1;
+
+ // Pseudonymized `extension_id` field (see also
+ // content::PseudonymizationUtil::PseudonymizeString method).
+ optional uint32 pseudonymized_extension_id = 2;
+}
+
+message SiteInstance {
+ // The ID of the SiteInstance.
+ optional int32 site_instance_id = 1;
+
+ // The ID of the BrowsingInstance that the SiteInstance belongs to.
+ optional int32 browsing_instance_id = 2;
+
+ // Whether the SiteInstance is the "default SiteInstance" or not. Non-isolated
+ // sites on Android are not assigned to their own specific per-site process,
+ // and shares SiteInstances with each other (the default SiteInstance).
+ optional bool is_default = 3;
+
+ // Whether this SiteInstance has a running process associated with it.
+ optional bool has_process = 4;
+
+ // Returns the total active WebContents count for this SiteInstance and all
+ // related SiteInstances in the same BrowsingInstance.
+ optional int32 related_active_contents_count = 5;
+
+ // The number of active RenderFrameHosts which belong to this SiteInstance.
+ optional int32 active_rfh_count = 6;
+}
+
+message RenderViewHost {
+ // The RenderViewHostMapId for the RenderViewHost.
+ optional int32 rvh_map_id = 1;
+
+ // The routing ID for the RenderViewHost.
+ optional int32 routing_id = 2;
+
+ // The process ID of the RenderViewHost.
+ optional int32 process_id = 3;
+
+ // Whether the RenderViewHost is in back/forward cache or not.
+ optional bool is_in_back_forward_cache = 4;
+
+ // Whether the renderer-side RenderView is created.
+ optional bool renderer_view_created = 5;
+}
+
+message RenderFrameProxyHost {
+ // The routing ID for the RenderFrameProxyHost.
+ optional int32 routing_id = 1;
+
+ // The process ID of the RenderFrameProxyHost.
+ optional int32 process_id = 2;
+
+ // The RenderViewHostMapId of the RenderViewHost associated with the
+ // RenderFrameProxyHost.
+ optional int32 rvh_map_id = 3;
+
+ // The SiteInstanceId of the SiteInstance associated with the
+ // RenderFrameProxyHost.
+ optional int32 site_instance_id = 4;
+
+ // Whether the renderer-side RenderFrameProxy is live or not.
+ optional bool is_render_frame_proxy_live = 5;
+}
+
message ChromeTrackEvent {
// Extension range for Chrome: 1000-1999
- // Next ID: 1017
+ // Next ID: 1022
extend TrackEvent {
optional ChromeAppState chrome_app_state = 1000;
@@ -173,8 +338,23 @@
optional ChromeHashedPerformanceMark chrome_hashed_performance_mark = 1011;
- // reserved 1012 to 1015.
+ optional RenderProcessHost render_process_host = 1012;
+ optional RenderProcessHostCleanup render_process_host_cleanup = 1013;
+ optional RenderProcessHostListener render_process_host_listener_changed =
+ 1014;
+ optional ChildProcessLauncherPriority child_process_launcher_priority =
+ 1015;
optional ResourceBundle resource_bundle = 1016;
+
+ optional ChromeWebAppBadNavigate chrome_web_app_bad_navigate = 1017;
+
+ optional ChromeExtensionId chrome_extension_id = 1018;
+
+ optional SiteInstance site_instance = 1019;
+
+ optional RenderViewHost render_view_host = 1020;
+
+ optional RenderFrameProxyHost render_frame_proxy_host = 1021;
}
}
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index f761a53..2434460 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -128,6 +128,8 @@
"../../gn:default_deps",
]
sources = [
+ "test/tmp_dir_tree.cc",
+ "test/tmp_dir_tree.h",
"test/utils.cc",
"test/utils.h",
"test/vm_test_utils.cc",
diff --git a/src/base/file_utils.cc b/src/base/file_utils.cc
index 9b92af2..7ccbad4 100644
--- a/src/base/file_utils.cc
+++ b/src/base/file_utils.cc
@@ -20,10 +20,14 @@
#include <sys/types.h>
#include <algorithm>
+#include <deque>
+#include <string>
+#include <vector>
#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/platform_handle.h"
+#include "perfetto/base/status.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/utils.h"
@@ -40,7 +44,7 @@
namespace base {
namespace {
constexpr size_t kBufSize = 2048;
-}
+} // namespace
ssize_t Read(int fd, void* dst, size_t dst_size) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
@@ -208,5 +212,114 @@
#endif
}
+base::Status ListFilesRecursive(const std::string& dir_path,
+ std::vector<std::string>& output) {
+ std::string root_dir_path = dir_path;
+ if (root_dir_path.back() == '\\') {
+ root_dir_path.back() = '/';
+ } else if (root_dir_path.back() != '/') {
+ root_dir_path.push_back('/');
+ }
+
+ // dir_queue contains full paths to the directories. The paths include the
+ // root_dir_path at the beginning and the trailing slash at the end.
+ std::deque<std::string> dir_queue;
+ dir_queue.push_back(root_dir_path);
+
+ while (!dir_queue.empty()) {
+ const std::string cur_dir = std::move(dir_queue.front());
+ dir_queue.pop_front();
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+ return base::ErrStatus("ListFilesRecursive not supported yet");
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ std::string glob_path = cur_dir + "*";
+ // + 1 because we also have to count the NULL terminator.
+ if (glob_path.length() + 1 > MAX_PATH)
+ return base::ErrStatus("Directory path %s is too long", dir_path.c_str());
+ WIN32_FIND_DATAA ffd;
+ // We do not use a ScopedResource for the HANDLE from FindFirstFile because
+ // the invalid value INVALID_HANDLE_VALUE is not a constexpr under some
+ // compile configurations, and thus cannot be used as a template argument.
+ HANDLE hFind = FindFirstFileA(glob_path.c_str(), &ffd);
+ if (hFind == INVALID_HANDLE_VALUE) {
+ // For empty directories, there should be at least one entry '.'.
+ // If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory
+ // couldn't be accessed.
+ FindClose(hFind);
+ return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
+ }
+ do {
+ if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0)
+ continue;
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ std::string subdir_path = cur_dir + ffd.cFileName + '/';
+ dir_queue.push_back(subdir_path);
+ } else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) {
+ const std::string full_path = cur_dir + ffd.cFileName;
+ PERFETTO_CHECK(full_path.length() > root_dir_path.length());
+ output.push_back(full_path.substr(root_dir_path.length()));
+ }
+ } while (FindNextFileA(hFind, &ffd));
+ FindClose(hFind);
+#else
+ ScopedDir dir = ScopedDir(opendir(cur_dir.c_str()));
+ if (!dir) {
+ return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
+ }
+ for (auto* dirent = readdir(dir.get()); dirent != nullptr;
+ dirent = readdir(dir.get())) {
+ if (strcmp(dirent->d_name, ".") == 0 ||
+ strcmp(dirent->d_name, "..") == 0) {
+ continue;
+ }
+ if (dirent->d_type == DT_DIR) {
+ dir_queue.push_back(cur_dir + dirent->d_name + '/');
+ } else if (dirent->d_type == DT_REG) {
+ const std::string full_path = cur_dir + dirent->d_name;
+ PERFETTO_CHECK(full_path.length() > root_dir_path.length());
+ output.push_back(full_path.substr(root_dir_path.length()));
+ }
+ }
+#endif
+ }
+ return base::OkStatus();
+}
+
+std::string GetFileExtension(const std::string& filename) {
+ auto ext_idx = filename.rfind('.');
+ if (ext_idx == std::string::npos)
+ return std::string();
+ return filename.substr(ext_idx);
+}
+
+base::Optional<size_t> GetFileSize(const std::string& file_path) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ HANDLE file =
+ CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (file == INVALID_HANDLE_VALUE) {
+ return nullopt;
+ }
+ LARGE_INTEGER file_size;
+ file_size.QuadPart = 0;
+ BOOL ok = GetFileSizeEx(file, &file_size);
+ CloseHandle(file);
+ if (!ok) {
+ return nullopt;
+ }
+ return static_cast<size_t>(file_size.QuadPart);
+#else
+ base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC));
+ if (!fd) {
+ return nullopt;
+ }
+ struct stat buf{};
+ if (fstat(*fd, &buf) == -1) {
+ return nullopt;
+ }
+ return static_cast<size_t>(buf.st_size);
+#endif
+}
+
} // namespace base
} // namespace perfetto
diff --git a/src/base/logging.cc b/src/base/logging.cc
index 5b251d6..cc47b9b 100644
--- a/src/base/logging.cc
+++ b/src/base/logging.cc
@@ -104,8 +104,9 @@
break;
}
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
- !PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_WASM) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
static const bool use_colors = isatty(STDERR_FILENO);
#else
static const bool use_colors = false;
diff --git a/src/base/paged_memory_unittest.cc b/src/base/paged_memory_unittest.cc
index fd2790d..7e3508b 100644
--- a/src/base/paged_memory_unittest.cc
+++ b/src/base/paged_memory_unittest.cc
@@ -36,12 +36,16 @@
TEST(PagedMemoryTest, Basic) {
const size_t kNumPages = 10;
const size_t kSize = 4096 * kNumPages;
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
void* ptr_raw = nullptr;
+#endif
{
PagedMemory mem = PagedMemory::Allocate(kSize);
ASSERT_TRUE(mem.IsValid());
ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(mem.Get()) % 4096);
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
ptr_raw = mem.Get();
+#endif
for (size_t i = 0; i < kSize / sizeof(uint64_t); i++)
ASSERT_EQ(0u, *(reinterpret_cast<uint64_t*>(mem.Get()) + i));
@@ -93,11 +97,15 @@
TEST(PagedMemoryTest, Uncommitted) {
constexpr size_t kNumPages = 4096;
constexpr size_t kSize = 4096 * kNumPages;
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
char* ptr_raw = nullptr;
+#endif
{
PagedMemory mem = PagedMemory::Allocate(kSize, PagedMemory::kDontCommit);
ASSERT_TRUE(mem.IsValid());
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
ptr_raw = reinterpret_cast<char*>(mem.Get());
+#endif
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
// Windows only commits the first 1024 pages.
diff --git a/src/base/string_utils.cc b/src/base/string_utils.cc
index c0b0780..9d5ae24 100644
--- a/src/base/string_utils.cc
+++ b/src/base/string_utils.cc
@@ -16,15 +16,15 @@
#include "perfetto/ext/base/string_utils.h"
-#include <inttypes.h>
#include <locale.h>
#include <string.h>
+#include <algorithm>
#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
#include <xlocale.h>
#endif
-#include <algorithm>
+#include <cinttypes>
#include "perfetto/base/logging.h"
@@ -48,46 +48,17 @@
#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;
}
+bool StartsWithAny(const std::string& str,
+ const std::vector<std::string>& prefixes) {
+ return std::any_of(
+ prefixes.begin(), prefixes.end(),
+ [&str](const std::string& prefix) { return StartsWith(str, prefix); });
+}
+
bool EndsWith(const std::string& str, const std::string& suffix) {
if (suffix.size() > str.size())
return false;
diff --git a/src/base/string_utils_unittest.cc b/src/base/string_utils_unittest.cc
index 5c41f16..2c7108d 100644
--- a/src/base/string_utils_unittest.cc
+++ b/src/base/string_utils_unittest.cc
@@ -156,6 +156,14 @@
EXPECT_FALSE(StartsWith("", "ab"));
}
+TEST(StringUtilsTest, StartsWithAny) {
+ EXPECT_FALSE(StartsWithAny("", {"a", "b"}));
+ EXPECT_FALSE(StartsWithAny("abcd", {}));
+ EXPECT_FALSE(StartsWithAny("", {}));
+ EXPECT_TRUE(StartsWithAny("abcd", {"ac", "ab"}));
+ EXPECT_FALSE(StartsWithAny("abcd", {"bc", "ac"}));
+}
+
TEST(StringUtilsTest, EndsWith) {
EXPECT_TRUE(EndsWith("", ""));
EXPECT_TRUE(EndsWith("abc", ""));
diff --git a/src/base/string_view_unittest.cc b/src/base/string_view_unittest.cc
index 5bda159..848e51d 100644
--- a/src/base/string_view_unittest.cc
+++ b/src/base/string_view_unittest.cc
@@ -155,6 +155,20 @@
EXPECT_FALSE(StringView("foo") >= StringView("fooo"));
EXPECT_TRUE(StringView("fooo") >= StringView("foo"));
EXPECT_FALSE(StringView("bar") >= StringView("foo"));
+
+ // Test StartsWith.
+ EXPECT_TRUE(StringView().StartsWith(StringView()));
+ EXPECT_TRUE(StringView().StartsWith(StringView("")));
+ EXPECT_TRUE(StringView("").StartsWith(StringView("")));
+ EXPECT_TRUE(StringView("").StartsWith(StringView()));
+ EXPECT_TRUE(StringView("foo").StartsWith(StringView()));
+ EXPECT_TRUE(StringView("foo").StartsWith(StringView("")));
+ EXPECT_FALSE(StringView().StartsWith("foo"));
+ EXPECT_FALSE(StringView("").StartsWith("foo"));
+ EXPECT_TRUE(StringView("foo").StartsWith("foo"));
+ EXPECT_TRUE(StringView("foorbar").StartsWith("foo"));
+ EXPECT_FALSE(StringView("foorbar").StartsWith("bar"));
+ EXPECT_FALSE(StringView("foo").StartsWith("fooo"));
}
TEST(StringViewTest, HashCollisions) {
diff --git a/src/base/test/tmp_dir_tree.cc b/src/base/test/tmp_dir_tree.cc
new file mode 100644
index 0000000..9ed785f
--- /dev/null
+++ b/src/base/test/tmp_dir_tree.cc
@@ -0,0 +1,55 @@
+/*
+ * 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/base/test/tmp_dir_tree.h"
+
+#include "perfetto/ext/base/file_utils.h"
+#include "perfetto/ext/base/scoped_file.h"
+
+namespace perfetto {
+namespace base {
+
+TmpDirTree::TmpDirTree() : tmp_dir_(base::TempDir::Create()) {}
+
+TmpDirTree::~TmpDirTree() {
+ for (; !files_to_remove_.empty(); files_to_remove_.pop()) {
+ PERFETTO_CHECK(remove(AbsolutePath(files_to_remove_.top()).c_str()) == 0);
+ }
+ for (; !dirs_to_remove_.empty(); dirs_to_remove_.pop()) {
+ base::Rmdir(AbsolutePath(dirs_to_remove_.top()));
+ }
+}
+
+std::string TmpDirTree::AbsolutePath(const std::string& relative_path) const {
+ return path() + "/" + relative_path;
+}
+
+void TmpDirTree::AddDir(const std::string& relative_path) {
+ dirs_to_remove_.push(relative_path);
+ PERFETTO_CHECK(base::Mkdir(AbsolutePath(relative_path)));
+}
+
+void TmpDirTree::AddFile(const std::string& relative_path,
+ const std::string& content) {
+ files_to_remove_.push(relative_path);
+ base::ScopedFile fd(base::OpenFile(AbsolutePath(relative_path),
+ O_WRONLY | O_CREAT | O_TRUNC, 0600));
+ PERFETTO_CHECK(base::WriteAll(fd.get(), content.c_str(), content.size()) ==
+ static_cast<ssize_t>(content.size()));
+}
+
+} // namespace base
+} // namespace perfetto
diff --git a/src/base/test/tmp_dir_tree.h b/src/base/test/tmp_dir_tree.h
new file mode 100644
index 0000000..6bb730c
--- /dev/null
+++ b/src/base/test/tmp_dir_tree.h
@@ -0,0 +1,62 @@
+/*
+ * 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_BASE_TEST_TMP_DIR_TREE_H_
+#define SRC_BASE_TEST_TMP_DIR_TREE_H_
+
+#include <stack>
+#include <string>
+
+#include "perfetto/ext/base/temp_file.h"
+
+namespace perfetto {
+namespace base {
+
+// Helper to construct and automatically destroy temporary file hierarchies in
+// tests.
+class TmpDirTree {
+ public:
+ TmpDirTree();
+ virtual ~TmpDirTree();
+
+ // Returns the absolute path where the temporary hierarchy is located.
+ const std::string& path() const { return tmp_dir_.path(); }
+
+ // Prepends `path()` to `relative_path` (making it an absolute path).
+ std::string AbsolutePath(const std::string& relative_path) const;
+
+ // Creates a directory at `relative_path`. All the parent directories should
+ // have been created. PERFETTO_CHECK()s that the operation succeeds.
+ void AddDir(const std::string& relative_path);
+
+ // Creates a file at `relative_path` which contains `content`. All the parent
+ // directories should have been created. PERFETTO_CHECK()s that the operation
+ // succeeds.
+ void AddFile(const std::string& relative_path, const std::string& content);
+
+ private:
+ TmpDirTree(const TmpDirTree&) = delete;
+ TmpDirTree& operator=(const TmpDirTree&) = delete;
+
+ base::TempDir tmp_dir_;
+ std::stack<std::string> dirs_to_remove_;
+ std::stack<std::string> files_to_remove_;
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // SRC_BASE_TEST_TMP_DIR_TREE_H_
diff --git a/src/base/utils.cc b/src/base/utils.cc
index 041e010..9b145fb 100644
--- a/src/base/utils.cc
+++ b/src/base/utils.cc
@@ -181,9 +181,9 @@
auto path = GetCurExecutablePath();
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
// Paths in Windows can have both kinds of slashes (mingw vs msvc).
- path = path.substr(0, path.find_last_of("\\"));
+ path = path.substr(0, path.find_last_of('\\'));
#endif
- path = path.substr(0, path.find_last_of("/"));
+ path = path.substr(0, path.find_last_of('/'));
return path;
}
diff --git a/src/base/watchdog_posix.cc b/src/base/watchdog_posix.cc
index fea7cd9..bd540a1 100644
--- a/src/base/watchdog_posix.cc
+++ b/src/base/watchdog_posix.cc
@@ -19,10 +19,10 @@
#if PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
#include <fcntl.h>
-#include <inttypes.h>
#include <signal.h>
#include <stdint.h>
+#include <cinttypes>
#include <fstream>
#include <thread>
@@ -256,7 +256,11 @@
struct sigevent sev = {};
timer_t timerid;
sev.sigev_notify = SIGEV_THREAD_ID;
+#if defined(__GLIBC__)
sev._sigev_un._tid = base::GetThreadId();
+#else
+ sev.sigev_notify_thread_id = base::GetThreadId();
+#endif
sev.sigev_signo = SIGABRT;
PERFETTO_CHECK(timer_create(CLOCK_MONOTONIC, &sev, &timerid) != -1);
timerid_ = base::make_optional(timerid);
diff --git a/src/ipc/buffered_frame_deserializer.cc b/src/ipc/buffered_frame_deserializer.cc
index d893dfb..16d3c86 100644
--- a/src/ipc/buffered_frame_deserializer.cc
+++ b/src/ipc/buffered_frame_deserializer.cc
@@ -16,9 +16,8 @@
#include "src/ipc/buffered_frame_deserializer.h"
-#include <inttypes.h>
-
#include <algorithm>
+#include <cinttypes>
#include <type_traits>
#include <utility>
diff --git a/src/ipc/client_impl.cc b/src/ipc/client_impl.cc
index 540656f..46cf9af 100644
--- a/src/ipc/client_impl.cc
+++ b/src/ipc/client_impl.cc
@@ -17,8 +17,8 @@
#include "src/ipc/client_impl.h"
#include <fcntl.h>
-#include <inttypes.h>
+#include <cinttypes>
#include <utility>
#include "perfetto/base/task_runner.h"
diff --git a/src/ipc/host_impl.cc b/src/ipc/host_impl.cc
index d0f370c..9467ca9 100644
--- a/src/ipc/host_impl.cc
+++ b/src/ipc/host_impl.cc
@@ -16,9 +16,8 @@
#include "src/ipc/host_impl.h"
-#include <inttypes.h>
-
#include <algorithm>
+#include <cinttypes>
#include <utility>
#include "perfetto/base/task_runner.h"
diff --git a/src/ipc/test/test_socket.h b/src/ipc/test/test_socket.h
index e55a8df..eaafd73 100644
--- a/src/ipc/test/test_socket.h
+++ b/src/ipc/test/test_socket.h
@@ -17,10 +17,11 @@
#ifndef SRC_IPC_TEST_TEST_SOCKET_H_
#define SRC_IPC_TEST_TEST_SOCKET_H_
-#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
+#include <cinttypes>
+
#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/unix_socket.h"
diff --git a/src/kallsyms/kernel_symbol_map.cc b/src/kallsyms/kernel_symbol_map.cc
index 126d6dd..0e4c374 100644
--- a/src/kallsyms/kernel_symbol_map.cc
+++ b/src/kallsyms/kernel_symbol_map.cc
@@ -26,10 +26,10 @@
#include "perfetto/ext/base/utils.h"
#include "perfetto/protozero/proto_utils.h"
-#include <inttypes.h>
#include <stdio.h>
#include <algorithm>
+#include <cinttypes>
#include <functional>
#include <map>
#include <utility>
diff --git a/src/kallsyms/kernel_symbol_map_unittest.cc b/src/kallsyms/kernel_symbol_map_unittest.cc
index deba34a..9cecdda 100644
--- a/src/kallsyms/kernel_symbol_map_unittest.cc
+++ b/src/kallsyms/kernel_symbol_map_unittest.cc
@@ -16,8 +16,7 @@
#include "src/kallsyms/kernel_symbol_map.h"
-#include <inttypes.h>
-
+#include <cinttypes>
#include <random>
#include <unordered_map>
diff --git a/src/kallsyms/lazy_kernel_symbolizer_unittest.cc b/src/kallsyms/lazy_kernel_symbolizer_unittest.cc
index c219dda..ca463ba 100644
--- a/src/kallsyms/lazy_kernel_symbolizer_unittest.cc
+++ b/src/kallsyms/lazy_kernel_symbolizer_unittest.cc
@@ -16,7 +16,7 @@
#include "src/kallsyms/lazy_kernel_symbolizer.h"
-#include <inttypes.h>
+#include <cinttypes>
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/temp_file.h"
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 6bca082..7bed31f 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -936,10 +936,6 @@
}
if (save_to_incidentd_) {
- if (!uuid_.empty()) {
- base::Uuid uuid(uuid_);
- PERFETTO_LOG("go/trace-uuid/%s", uuid.ToPrettyString().c_str());
- }
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
SaveTraceIntoDropboxAndIncidentOrCrash();
#endif
diff --git a/src/perfetto_cmd/perfetto_cmd_android.cc b/src/perfetto_cmd/perfetto_cmd_android.cc
index fe2572c..a4ed211 100644
--- a/src/perfetto_cmd/perfetto_cmd_android.cc
+++ b/src/perfetto_cmd/perfetto_cmd_android.cc
@@ -16,9 +16,10 @@
#include "src/perfetto_cmd/perfetto_cmd.h"
-#include <inttypes.h>
#include <sys/sendfile.h>
+#include <cinttypes>
+
#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/file_utils.h"
@@ -48,6 +49,12 @@
// 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_);
+ }
+
// Ask incidentd to create a report, which will read the file we just
// wrote.
const auto& cfg = trace_config_->incident_report_config();
diff --git a/src/perfetto_cmd/rate_limiter.cc b/src/perfetto_cmd/rate_limiter.cc
index 65e26e3..75e36cb 100644
--- a/src/perfetto_cmd/rate_limiter.cc
+++ b/src/perfetto_cmd/rate_limiter.cc
@@ -17,11 +17,11 @@
#include "src/perfetto_cmd/rate_limiter.h"
#include <fcntl.h>
-#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <algorithm>
+#include <cinttypes>
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/file_utils.h"
diff --git a/src/profiling/common/proc_utils.cc b/src/profiling/common/proc_utils.cc
index c2d1e55..fab2261 100644
--- a/src/profiling/common/proc_utils.cc
+++ b/src/profiling/common/proc_utils.cc
@@ -16,10 +16,11 @@
#include "src/profiling/common/proc_utils.h"
-#include <inttypes.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <cinttypes>
+
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/profiling/normalize.h"
diff --git a/src/profiling/common/proc_utils.h b/src/profiling/common/proc_utils.h
index facd10e..6376478 100644
--- a/src/profiling/common/proc_utils.h
+++ b/src/profiling/common/proc_utils.h
@@ -17,9 +17,9 @@
#ifndef SRC_PROFILING_COMMON_PROC_UTILS_H_
#define SRC_PROFILING_COMMON_PROC_UTILS_H_
-#include <inttypes.h>
#include <sys/types.h>
+#include <cinttypes>
#include <set>
#include <vector>
diff --git a/src/profiling/common/producer_support.h b/src/profiling/common/producer_support.h
index 4e6b856..6f54045 100644
--- a/src/profiling/common/producer_support.h
+++ b/src/profiling/common/producer_support.h
@@ -17,7 +17,7 @@
#ifndef SRC_PROFILING_COMMON_PRODUCER_SUPPORT_H_
#define SRC_PROFILING_COMMON_PRODUCER_SUPPORT_H_
-#include <inttypes.h>
+#include <cinttypes>
#include <string>
#include "perfetto/tracing/core/forward_decls.h"
diff --git a/src/profiling/common/profiler_guardrails.h b/src/profiling/common/profiler_guardrails.h
index f89c0c2..e9e9d47 100644
--- a/src/profiling/common/profiler_guardrails.h
+++ b/src/profiling/common/profiler_guardrails.h
@@ -18,9 +18,10 @@
#define SRC_PROFILING_COMMON_PROFILER_GUARDRAILS_H_
#include <fcntl.h>
-#include <inttypes.h>
#include <unistd.h>
+#include <cinttypes>
+
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/scoped_file.h"
diff --git a/src/profiling/common/profiler_guardrails_unittest.cc b/src/profiling/common/profiler_guardrails_unittest.cc
index ef8a450..ca9d1b2 100644
--- a/src/profiling/common/profiler_guardrails_unittest.cc
+++ b/src/profiling/common/profiler_guardrails_unittest.cc
@@ -16,9 +16,9 @@
#include "src/profiling/common/profiler_guardrails.h"
-#include <inttypes.h>
#include <unistd.h>
+#include <cinttypes>
#include <map>
#include "perfetto/ext/base/file_utils.h"
diff --git a/src/profiling/common/unwind_support.cc b/src/profiling/common/unwind_support.cc
index 5302015..3599d54 100644
--- a/src/profiling/common/unwind_support.cc
+++ b/src/profiling/common/unwind_support.cc
@@ -16,7 +16,7 @@
#include "src/profiling/common/unwind_support.h"
-#include <inttypes.h>
+#include <cinttypes>
#include <procinfo/process_map.h>
#include <unwindstack/Maps.h>
diff --git a/src/profiling/memory/bookkeeping.cc b/src/profiling/memory/bookkeeping.cc
index 3439db4..828280d 100644
--- a/src/profiling/memory/bookkeeping.cc
+++ b/src/profiling/memory/bookkeeping.cc
@@ -17,10 +17,11 @@
#include "src/profiling/memory/bookkeeping.h"
#include <fcntl.h>
-#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <cinttypes>
+
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/scoped_file.h"
diff --git a/src/profiling/memory/bookkeeping_dump.h b/src/profiling/memory/bookkeeping_dump.h
index 9c37676..115653a 100644
--- a/src/profiling/memory/bookkeeping_dump.h
+++ b/src/profiling/memory/bookkeeping_dump.h
@@ -17,22 +17,20 @@
#ifndef SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_
#define SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_
+#include <cinttypes>
#include <functional>
#include <set>
-#include <inttypes.h>
+#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "src/profiling/common/interner.h"
+#include "src/profiling/common/interning_output.h"
+#include "src/profiling/memory/bookkeeping.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-
-#include "src/profiling/common/interner.h"
-#include "src/profiling/common/interning_output.h"
-#include "src/profiling/memory/bookkeeping.h"
-
namespace perfetto {
namespace profiling {
diff --git a/src/profiling/memory/client.cc b/src/profiling/memory/client.cc
index 4a84a20..cd06150 100644
--- a/src/profiling/memory/client.cc
+++ b/src/profiling/memory/client.cc
@@ -16,13 +16,17 @@
#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 <algorithm>
+#include <atomic>
+#include <cinttypes>
+#include <new>
+
#include <unwindstack/MachineArm.h>
#include <unwindstack/MachineArm64.h>
#include <unwindstack/MachineMips.h>
@@ -32,10 +36,6 @@
#include <unwindstack/Regs.h>
#include <unwindstack/RegsGetLocal.h>
-#include <algorithm>
-#include <atomic>
-#include <new>
-
#include "perfetto/base/compiler.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/thread_utils.h"
diff --git a/src/profiling/memory/client_api.cc b/src/profiling/memory/client_api.cc
index 9444293..c1b96a1 100644
--- a/src/profiling/memory/client_api.cc
+++ b/src/profiling/memory/client_api.cc
@@ -17,7 +17,6 @@
#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>
@@ -27,6 +26,7 @@
#include <unistd.h>
#include <atomic>
+#include <cinttypes>
#include <memory>
#include <tuple>
#include <type_traits>
@@ -113,8 +113,9 @@
}
constexpr auto kMinHeapId = 1;
+constexpr auto kMaxNumHeaps = 256;
-AHeapInfo g_heaps[256];
+AHeapInfo g_heaps[kMaxNumHeaps];
AHeapInfo& GetHeap(uint32_t id) {
return g_heaps[id];
@@ -136,7 +137,7 @@
// This can get called while holding the spinlock (in normal operation), or
// without holding the spinlock (from OnSpinlockTimeout).
void DisableAllHeaps() {
- bool disabled[perfetto::base::ArraySize(g_heaps)] = {};
+ bool disabled[kMaxNumHeaps] = {};
uint32_t max_heap = g_next_heap_id.load();
// This has to be done in two passes, in case the disabled_callback for one
// enabled heap uses another. In that case, the callbacks for the other heap
@@ -297,7 +298,7 @@
}
uint32_t next_id = g_next_heap_id.fetch_add(1);
- if (next_id >= perfetto::base::ArraySize(g_heaps)) {
+ if (next_id >= kMaxNumHeaps) {
return nullptr;
}
@@ -540,7 +541,7 @@
}
uint32_t max_heap = g_next_heap_id.load();
- bool heaps_enabled[perfetto::base::ArraySize(g_heaps)] = {};
+ bool heaps_enabled[kMaxNumHeaps] = {};
PERFETTO_LOG("%s: heapprofd_client initialized.", getprogname());
{
diff --git a/src/profiling/memory/client_api_noop.cc b/src/profiling/memory/client_api_noop.cc
index 0f3732f..2287661 100644
--- a/src/profiling/memory/client_api_noop.cc
+++ b/src/profiling/memory/client_api_noop.cc
@@ -17,7 +17,7 @@
#include "perfetto/heap_profile.h"
#include "src/profiling/memory/heap_profile_internal.h"
-#include <inttypes.h>
+#include <cinttypes>
__attribute__((visibility("default"))) uint64_t
AHeapProfileEnableCallbackInfo_getSamplingInterval(
diff --git a/src/profiling/memory/heap_profile_internal.h b/src/profiling/memory/heap_profile_internal.h
index 8e9a980..0542014 100644
--- a/src/profiling/memory/heap_profile_internal.h
+++ b/src/profiling/memory/heap_profile_internal.h
@@ -17,9 +17,10 @@
#ifndef SRC_PROFILING_MEMORY_HEAP_PROFILE_INTERNAL_H_
#define SRC_PROFILING_MEMORY_HEAP_PROFILE_INTERNAL_H_
-#include <inttypes.h>
#include <stdlib.h>
+#include <cinttypes>
+
#pragma GCC diagnostic push
#if defined(__clang__)
diff --git a/src/profiling/memory/heapprofd_end_to_end_test.cc b/src/profiling/memory/heapprofd_end_to_end_test.cc
index 525d865..3db57ee 100644
--- a/src/profiling/memory/heapprofd_end_to_end_test.cc
+++ b/src/profiling/memory/heapprofd_end_to_end_test.cc
@@ -1750,6 +1750,10 @@
EXPECT_GT(total_allocated, 0u);
}
+// Disable these tests when running with sanitizers. They (double) fork and that
+// seems to cause flaky crashes with sanitizers.
+#if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && \
+ !defined(MEMORY_SANITIZER) && !defined(LEAK_SANITIZER)
// 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.
@@ -1771,6 +1775,8 @@
std::make_tuple(TestMode::kCentral, AllocatorMode::kCustom)),
TestSuffix);
#endif
+#endif
+
} // namespace
} // namespace profiling
diff --git a/src/profiling/memory/heapprofd_producer.cc b/src/profiling/memory/heapprofd_producer.cc
index 6a47344..fdfccfa 100644
--- a/src/profiling/memory/heapprofd_producer.cc
+++ b/src/profiling/memory/heapprofd_producer.cc
@@ -16,16 +16,16 @@
#include "src/profiling/memory/heapprofd_producer.h"
-#include <algorithm>
-#include <functional>
-#include <string>
-
-#include <inttypes.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <algorithm>
+#include <cinttypes>
+#include <functional>
+#include <string>
+
#include "perfetto/base/compiler.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/file_utils.h"
@@ -99,7 +99,6 @@
return false;
}
-
bool IsFile(int fd, const char* fn) {
struct stat fdstat;
struct stat fnstat;
@@ -147,7 +146,8 @@
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();
+ 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();
diff --git a/src/profiling/memory/heapprofd_producer.h b/src/profiling/memory/heapprofd_producer.h
index 51cc0c7..4c57a5d 100644
--- a/src/profiling/memory/heapprofd_producer.h
+++ b/src/profiling/memory/heapprofd_producer.h
@@ -18,23 +18,20 @@
#define SRC_PROFILING_MEMORY_HEAPPROFD_PRODUCER_H_
#include <array>
+#include <cinttypes>
#include <functional>
#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"
#include "perfetto/ext/base/unix_task_runner.h"
-
#include "perfetto/ext/tracing/core/basic_types.h"
#include "perfetto/ext/tracing/core/producer.h"
#include "perfetto/ext/tracing/core/trace_writer.h"
#include "perfetto/ext/tracing/core/tracing_service.h"
#include "perfetto/tracing/core/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"
diff --git a/src/profiling/memory/include/perfetto/heap_profile.h b/src/profiling/memory/include/perfetto/heap_profile.h
index 33e797b..b4e0e62 100644
--- a/src/profiling/memory/include/perfetto/heap_profile.h
+++ b/src/profiling/memory/include/perfetto/heap_profile.h
@@ -59,9 +59,10 @@
#ifndef SRC_PROFILING_MEMORY_INCLUDE_PERFETTO_HEAP_PROFILE_H_
#define SRC_PROFILING_MEMORY_INCLUDE_PERFETTO_HEAP_PROFILE_H_
-#include <inttypes.h>
#include <stdlib.h>
+#include <cinttypes>
+
#pragma GCC diagnostic push
#if defined(__clang__)
diff --git a/src/profiling/memory/log_histogram.cc b/src/profiling/memory/log_histogram.cc
index 3db734f..3e7e328 100644
--- a/src/profiling/memory/log_histogram.cc
+++ b/src/profiling/memory/log_histogram.cc
@@ -16,9 +16,9 @@
#include "src/profiling/memory/log_histogram.h"
-#include <inttypes.h>
#include <stddef.h>
+#include <cinttypes>
#include <utility>
#include <vector>
diff --git a/src/profiling/memory/log_histogram.h b/src/profiling/memory/log_histogram.h
index 9b16b86..e016173 100644
--- a/src/profiling/memory/log_histogram.h
+++ b/src/profiling/memory/log_histogram.h
@@ -17,10 +17,10 @@
#ifndef SRC_PROFILING_MEMORY_LOG_HISTOGRAM_H_
#define SRC_PROFILING_MEMORY_LOG_HISTOGRAM_H_
-#include <inttypes.h>
#include <stddef.h>
#include <array>
+#include <cinttypes>
#include <utility>
#include <vector>
diff --git a/src/profiling/memory/malloc_interceptor_bionic_hooks.cc b/src/profiling/memory/malloc_interceptor_bionic_hooks.cc
index 2e63f23..0d5a92e 100644
--- a/src/profiling/memory/malloc_interceptor_bionic_hooks.cc
+++ b/src/profiling/memory/malloc_interceptor_bionic_hooks.cc
@@ -15,11 +15,11 @@
*/
#include <bionic/malloc.h>
-#include <inttypes.h>
#include <malloc.h>
#include <private/bionic_malloc_dispatch.h>
#include <atomic>
+#include <cinttypes>
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/utils.h"
diff --git a/src/profiling/memory/parse_smaps_unittest.cc b/src/profiling/memory/parse_smaps_unittest.cc
index 5708a2c..d59d9df 100644
--- a/src/profiling/memory/parse_smaps_unittest.cc
+++ b/src/profiling/memory/parse_smaps_unittest.cc
@@ -16,12 +16,12 @@
#include "perfetto/profiling/parse_smaps.h"
+#include <cinttypes>
+
#include "perfetto/ext/base/scoped_file.h"
#include "src/base/test/utils.h"
#include "test/gtest_and_gmock.h"
-#include <inttypes.h>
-
namespace perfetto {
namespace profiling {
diff --git a/src/profiling/memory/sampler.cc b/src/profiling/memory/sampler.cc
index a5e59db..9a05fc3 100644
--- a/src/profiling/memory/sampler.cc
+++ b/src/profiling/memory/sampler.cc
@@ -19,33 +19,10 @@
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..40e429f 100644
--- a/src/profiling/memory/sampler.h
+++ b/src/profiling/memory/sampler.h
@@ -29,8 +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
@@ -44,7 +42,11 @@
// NB: not thread-safe, requires external synchronization.
class Sampler {
public:
- void SetSamplingInterval(uint64_t sampling_interval);
+ void SetSamplingInterval(uint64_t sampling_interval) {
+ sampling_interval_ = sampling_interval;
+ sampling_rate_ = 1.0 / static_cast<double>(sampling_interval_);
+ 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,7 +54,7 @@
// 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));
}
@@ -83,7 +85,6 @@
}
uint64_t sampling_interval_;
- uint64_t passthrough_threshold_;
double sampling_rate_;
int64_t interval_to_next_sample_;
};
diff --git a/src/profiling/memory/sampler_unittest.cc b/src/profiling/memory/sampler_unittest.cc
index b3eca7b..409fa4c 100644
--- a/src/profiling/memory/sampler_unittest.cc
+++ b/src/profiling/memory/sampler_unittest.cc
@@ -27,8 +27,8 @@
TEST(SamplerTest, TestLarge) {
GetGlobalRandomEngineLocked().seed(1);
Sampler sampler;
- sampler.SetSamplingInterval(32768);
- EXPECT_EQ(sampler.SampleSize(160000u), 160000u);
+ sampler.SetSamplingInterval(512);
+ EXPECT_EQ(sampler.SampleSize(1024), 1024u);
}
TEST(SamplerTest, TestSmall) {
@@ -47,12 +47,6 @@
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/shared_ring_buffer.cc b/src/profiling/memory/shared_ring_buffer.cc
index bc56327..1120c7a 100644
--- a/src/profiling/memory/shared_ring_buffer.cc
+++ b/src/profiling/memory/shared_ring_buffer.cc
@@ -16,16 +16,16 @@
#include "src/profiling/memory/shared_ring_buffer.h"
-#include <atomic>
-#include <type_traits>
-
#include <errno.h>
#include <fcntl.h>
-#include <inttypes.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <atomic>
+#include <cinttypes>
+#include <type_traits>
+
#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/temp_file.h"
diff --git a/src/profiling/memory/unwinding.cc b/src/profiling/memory/unwinding.cc
index 5021949..12a2a02 100644
--- a/src/profiling/memory/unwinding.cc
+++ b/src/profiling/memory/unwinding.cc
@@ -228,14 +228,14 @@
DataSourceInstanceID ds_id = client_data.data_source_instance_id;
client_data_.erase(it);
+ // The erase invalidates the self pointer.
+ self = nullptr;
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);
}
diff --git a/src/profiling/memory/wire_protocol.h b/src/profiling/memory/wire_protocol.h
index f1989b7..164358f 100644
--- a/src/profiling/memory/wire_protocol.h
+++ b/src/profiling/memory/wire_protocol.h
@@ -20,7 +20,8 @@
#ifndef SRC_PROFILING_MEMORY_WIRE_PROTOCOL_H_
#define SRC_PROFILING_MEMORY_WIRE_PROTOCOL_H_
-#include <inttypes.h>
+#include <cinttypes>
+
#include <unwindstack/Elf.h>
#include <unwindstack/MachineArm.h>
#include <unwindstack/MachineArm64.h>
diff --git a/src/profiling/memory/wire_protocol_unittest.cc b/src/profiling/memory/wire_protocol_unittest.cc
index 3f7e494..873d977 100644
--- a/src/profiling/memory/wire_protocol_unittest.cc
+++ b/src/profiling/memory/wire_protocol_unittest.cc
@@ -95,12 +95,13 @@
WireMessage recv_msg;
ASSERT_TRUE(ReceiveWireMessage(reinterpret_cast<char*>(buf.data), buf.size,
&recv_msg));
- shmem_server->EndRead(std::move(buf));
ASSERT_EQ(recv_msg.record_type, msg.record_type);
ASSERT_EQ(*recv_msg.alloc_header, *msg.alloc_header);
ASSERT_EQ(recv_msg.payload_size, msg.payload_size);
ASSERT_STREQ(recv_msg.payload, msg.payload);
+
+ shmem_server->EndRead(std::move(buf));
}
TEST(WireProtocolTest, FreeMessage) {
@@ -123,11 +124,12 @@
WireMessage recv_msg;
ASSERT_TRUE(ReceiveWireMessage(reinterpret_cast<char*>(buf.data), buf.size,
&recv_msg));
- shmem_server->EndRead(std::move(buf));
ASSERT_EQ(recv_msg.record_type, msg.record_type);
ASSERT_EQ(*recv_msg.free_header, *msg.free_header);
ASSERT_EQ(recv_msg.payload_size, msg.payload_size);
+
+ shmem_server->EndRead(std::move(buf));
}
TEST(GetHeapSamplingInterval, Default) {
diff --git a/src/profiling/memory/wrap_allocators.cc b/src/profiling/memory/wrap_allocators.cc
index 696337a..e73c151 100644
--- a/src/profiling/memory/wrap_allocators.cc
+++ b/src/profiling/memory/wrap_allocators.cc
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-#include <inttypes.h>
#include <stdlib.h>
+#include <cinttypes>
+
#include "perfetto/ext/base/utils.h"
#include "perfetto/heap_profile.h"
#include "src/profiling/memory/wrap_allocators.h"
diff --git a/src/profiling/memory/wrap_allocators.h b/src/profiling/memory/wrap_allocators.h
index ce9fb3e..0d5a982 100644
--- a/src/profiling/memory/wrap_allocators.h
+++ b/src/profiling/memory/wrap_allocators.h
@@ -17,9 +17,10 @@
#ifndef SRC_PROFILING_MEMORY_WRAP_ALLOCATORS_H_
#define SRC_PROFILING_MEMORY_WRAP_ALLOCATORS_H_
-#include <inttypes.h>
#include <stdlib.h>
+#include <cinttypes>
+
namespace perfetto {
namespace profiling {
diff --git a/src/profiling/perf/event_config.cc b/src/profiling/perf/event_config.cc
index 7b5170e..4195cc3 100644
--- a/src/profiling/perf/event_config.cc
+++ b/src/profiling/perf/event_config.cc
@@ -156,23 +156,26 @@
}
base::Optional<PerfCounter> ToPerfCounter(
+ std::string name,
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);
+ return PerfCounter::BuiltinCounter(name, 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);
+ return PerfCounter::BuiltinCounter(name, 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);
+ return PerfCounter::BuiltinCounter(name, 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);
+ return PerfCounter::BuiltinCounter(name, 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));
@@ -183,24 +186,52 @@
} // namespace
// static
-PerfCounter PerfCounter::Counter(protos::gen::PerfEvents::Counter counter,
- uint32_t type,
- uint32_t config) {
+PerfCounter PerfCounter::BuiltinCounter(
+ std::string name,
+ protos::gen::PerfEvents::Counter counter,
+ uint32_t type,
+ uint64_t config) {
PerfCounter ret;
+ ret.type = PerfCounter::Type::kBuiltinCounter;
ret.counter = counter;
- ret.type = type;
- ret.config = config;
+ ret.name = std::move(name);
+
+ ret.attr_type = type;
+ ret.attr_config = config;
+ // none of the builtin counters require config1 and config2 at the moment
return ret;
}
// static
-PerfCounter PerfCounter::Tracepoint(
- protos::gen::PerfEvents::Tracepoint tracepoint,
- uint32_t id) {
+PerfCounter PerfCounter::Tracepoint(std::string name,
+ std::string tracepoint_name,
+ std::string tracepoint_filter,
+ uint64_t id) {
PerfCounter ret;
- ret.tracepoint = std::move(tracepoint);
- ret.type = PERF_TYPE_TRACEPOINT;
- ret.config = id;
+ ret.type = PerfCounter::Type::kTracepoint;
+ ret.tracepoint_name = std::move(tracepoint_name);
+ ret.tracepoint_filter = std::move(tracepoint_filter);
+ ret.name = std::move(name);
+
+ ret.attr_type = PERF_TYPE_TRACEPOINT;
+ ret.attr_config = id;
+ return ret;
+}
+
+// static
+PerfCounter PerfCounter::RawEvent(std::string name,
+ uint32_t type,
+ uint64_t config,
+ uint64_t config1,
+ uint64_t config2) {
+ PerfCounter ret;
+ ret.type = PerfCounter::Type::kRawEvent;
+ ret.name = std::move(name);
+
+ ret.attr_type = type;
+ ret.attr_config = config;
+ ret.attr_config1 = config1;
+ ret.attr_config2 = config2;
return ret;
}
@@ -237,8 +268,10 @@
// Timebase event. Default: CPU timer.
PerfCounter timebase_event;
+ std::string timebase_name = pb_config.timebase().name();
if (pb_config.timebase().has_counter()) {
- auto maybe_counter = ToPerfCounter(pb_config.timebase().counter());
+ auto maybe_counter =
+ ToPerfCounter(timebase_name, pb_config.timebase().counter());
if (!maybe_counter)
return base::nullopt;
timebase_event = *maybe_counter;
@@ -249,12 +282,18 @@
ParseTracepointAndResolveId(tracepoint_pb, tracepoint_id_lookup);
if (!maybe_id)
return base::nullopt;
- timebase_event = PerfCounter::Tracepoint(tracepoint_pb, *maybe_id);
+ timebase_event = PerfCounter::Tracepoint(
+ timebase_name, tracepoint_pb.name(), tracepoint_pb.filter(), *maybe_id);
+
+ } else if (pb_config.timebase().has_raw_event()) {
+ const auto& raw = pb_config.timebase().raw_event();
+ timebase_event = PerfCounter::RawEvent(
+ timebase_name, raw.type(), raw.config(), raw.config1(), raw.config2());
} else {
- timebase_event =
- PerfCounter::Counter(protos::gen::PerfEvents::PerfEvents::SW_CPU_CLOCK,
- PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK);
+ timebase_event = PerfCounter::BuiltinCounter(
+ timebase_name, protos::gen::PerfEvents::PerfEvents::SW_CPU_CLOCK,
+ PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK);
}
// Callstack sampling.
@@ -332,8 +371,10 @@
pe.disabled = 1; // will be activated via ioctl
// Sampling timebase.
- pe.type = timebase_event.type;
- pe.config = timebase_event.config;
+ pe.type = timebase_event.attr_type;
+ pe.config = timebase_event.attr_config;
+ pe.config1 = timebase_event.attr_config1;
+ pe.config2 = timebase_event.attr_config2;
if (sampling_frequency) {
pe.freq = true;
pe.sample_freq = sampling_frequency;
diff --git a/src/profiling/perf/event_config.h b/src/profiling/perf/event_config.h
index d75c7c8..782b05d 100644
--- a/src/profiling/perf/event_config.h
+++ b/src/profiling/perf/event_config.h
@@ -17,11 +17,11 @@
#ifndef SRC_PROFILING_PERF_EVENT_CONFIG_H_
#define SRC_PROFILING_PERF_EVENT_CONFIG_H_
+#include <cinttypes>
#include <functional>
#include <string>
#include <vector>
-#include <inttypes.h>
#include <linux/perf_event.h>
#include <stdint.h>
#include <sys/types.h>
@@ -51,27 +51,54 @@
uint32_t additional_cmdline_count = 0;
};
+// Describes a perf event for two purposes:
+// * encoding the event in the perf_event_open syscall
+// * echoing the counter's config in the trace packet defaults, so that the
+// parser can tell which datastream belongs to which counter.
+// Note: It's slightly odd to decode & pass around values we don't use outside
+// of reencoding back into a defaults proto. One option would be to carry the
+// Timebase proto, but this won't fit with the eventual support of multiple
+// counters, as at the proto level it'll be a distinct message from Timebase.
struct PerfCounter {
- // Either a predefined counter, or a tracepoint:
+ enum class Type { kBuiltinCounter, kTracepoint, kRawEvent };
+
+ Type type = Type::kBuiltinCounter;
+
+ // Optional config-supplied name for the counter, to identify it during
+ // trace parsing, does not affect the syscall.
+ std::string name;
+
+ // valid if kBuiltinCounter
protos::gen::PerfEvents::Counter counter =
protos::gen::PerfEvents::PerfEvents::UNKNOWN_COUNTER;
- protos::gen::PerfEvents::Tracepoint tracepoint;
+ // valid if kTracepoint. Example: "sched:sched_switch".
+ std::string tracepoint_name;
+ // valid if kTracepoint
+ std::string tracepoint_filter;
- // sycall-level description of the event:
- uint32_t type = 0; // perf_event_attr.type
- uint32_t config = 0; // perf_event_attr.config
+ // sycall-level description of the event (perf_event_attr):
+ uint32_t attr_type = 0;
+ uint64_t attr_config = 0;
+ uint64_t attr_config1 = 0; // optional extension
+ uint64_t attr_config2 = 0; // optional extension
- bool is_counter() const {
- return counter != protos::gen::PerfEvents::PerfEvents::UNKNOWN_COUNTER;
- }
- bool is_tracepoint() const { return type == PERF_TYPE_TRACEPOINT; }
+ Type event_type() const { return type; }
- static PerfCounter Counter(protos::gen::PerfEvents::Counter counter,
- uint32_t type,
- uint32_t config);
+ static PerfCounter BuiltinCounter(std::string name,
+ protos::gen::PerfEvents::Counter counter,
+ uint32_t type,
+ uint64_t config);
- static PerfCounter Tracepoint(protos::gen::PerfEvents::Tracepoint tracepoint,
- uint32_t id);
+ static PerfCounter Tracepoint(std::string name,
+ std::string tracepoint_name,
+ std::string tracepoint_filter,
+ uint64_t id);
+
+ static PerfCounter RawEvent(std::string name,
+ uint32_t type,
+ uint64_t config,
+ uint64_t config1,
+ uint64_t config2);
};
// Describes a single profiling configuration. Bridges the gap between the data
@@ -171,9 +198,9 @@
// 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
+ // * "@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.
diff --git a/src/profiling/perf/event_config_unittest.cc b/src/profiling/perf/event_config_unittest.cc
index c69d45d..30520f1 100644
--- a/src/profiling/perf/event_config_unittest.cc
+++ b/src/profiling/perf/event_config_unittest.cc
@@ -318,9 +318,10 @@
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_EQ(
+ event_config->perf_attr()->sample_type &
+ (PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER),
+ static_cast<uint64_t>(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);
diff --git a/src/profiling/perf/event_reader.cc b/src/profiling/perf/event_reader.cc
index 039afa3..de05f8b 100644
--- a/src/profiling/perf/event_reader.cc
+++ b/src/profiling/perf/event_reader.cc
@@ -68,13 +68,15 @@
// 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;
- }
+ if (event.type != PerfCounter::Type::kTracepoint ||
+ event.tracepoint_filter.empty()) {
+ return true;
+ }
+ PERFETTO_DCHECK(event.attr_type == PERF_TYPE_TRACEPOINT);
+
+ if (ioctl(fd, PERF_EVENT_IOC_SET_FILTER, event.tracepoint_filter.c_str())) {
+ PERFETTO_PLOG("Failed ioctl to set event filter");
+ return false;
}
return true;
}
diff --git a/src/profiling/perf/perf_producer.cc b/src/profiling/perf/perf_producer.cc
index b1c7e1f..f9ad9e2 100644
--- a/src/profiling/perf/perf_producer.cc
+++ b/src/profiling/perf/perf_producer.cc
@@ -115,16 +115,31 @@
// 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());
+ switch (timebase.event_type()) {
+ case PerfCounter::Type::kBuiltinCounter: {
+ timebase_pb->set_counter(
+ static_cast<protos::pbzero::PerfEvents::Counter>(timebase.counter));
+ break;
+ }
+ case PerfCounter::Type::kTracepoint: {
+ auto* tracepoint_pb = timebase_pb->set_tracepoint();
+ tracepoint_pb->set_name(timebase.tracepoint_name);
+ tracepoint_pb->set_filter(timebase.tracepoint_filter);
+ break;
+ }
+ case PerfCounter::Type::kRawEvent: {
+ auto* raw_pb = timebase_pb->set_raw_event();
+ raw_pb->set_type(timebase.attr_type);
+ raw_pb->set_config(timebase.attr_config);
+ raw_pb->set_config1(timebase.attr_config1);
+ raw_pb->set_config2(timebase.attr_config2);
+ break;
+ }
+ }
+
+ // optional name to identify the counter during parsing:
+ if (!timebase.name.empty()) {
+ timebase_pb->set_name(timebase.name);
}
}
diff --git a/src/profiling/perf/regs_parsing.cc b/src/profiling/perf/regs_parsing.cc
index 75c1a75..99bed42 100644
--- a/src/profiling/perf/regs_parsing.cc
+++ b/src/profiling/perf/regs_parsing.cc
@@ -16,10 +16,11 @@
#include "src/profiling/perf/regs_parsing.h"
-#include <inttypes.h>
#include <linux/perf_event.h>
#include <stdint.h>
#include <unistd.h>
+
+#include <cinttypes>
#include <memory>
#include <unwindstack/Elf.h>
diff --git a/src/profiling/perf/unwinding.cc b/src/profiling/perf/unwinding.cc
index 46dfc6b..699f370 100644
--- a/src/profiling/perf/unwinding.cc
+++ b/src/profiling/perf/unwinding.cc
@@ -16,10 +16,9 @@
#include "src/profiling/perf/unwinding.h"
+#include <cinttypes>
#include <mutex>
-#include <inttypes.h>
-
#include <unwindstack/Unwinder.h>
#include "perfetto/ext/base/metatrace.h"
diff --git a/src/profiling/symbolizer/BUILD.gn b/src/profiling/symbolizer/BUILD.gn
index 6989d0a..70dc091 100644
--- a/src/profiling/symbolizer/BUILD.gn
+++ b/src/profiling/symbolizer/BUILD.gn
@@ -19,9 +19,11 @@
public_deps = [ "../../../include/perfetto/ext/base" ]
deps = [ "../../../gn:default_deps" ]
sources = [
- "filesystem.h",
- "filesystem_posix.cc",
- "filesystem_windows.cc",
+ "breakpad_parser.cc",
+ "breakpad_parser.h",
+ "breakpad_symbolizer.cc",
+ "breakpad_symbolizer.h",
+ "elf.h",
"local_symbolizer.cc",
"local_symbolizer.h",
"scoped_read_mmap.h",
@@ -61,5 +63,9 @@
"../../../gn:gtest_and_gmock",
"../../base:test_support",
]
- sources = [ "local_symbolizer_unittest.cc" ]
+ sources = [
+ "breakpad_parser_unittest.cc",
+ "breakpad_symbolizer_unittest.cc",
+ "local_symbolizer_unittest.cc",
+ ]
}
diff --git a/src/profiling/symbolizer/breakpad_parser.cc b/src/profiling/symbolizer/breakpad_parser.cc
new file mode 100644
index 0000000..5c3c5c0
--- /dev/null
+++ b/src/profiling/symbolizer/breakpad_parser.cc
@@ -0,0 +1,215 @@
+/*
+ * 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 <memory>
+
+#include "src/profiling/symbolizer/breakpad_parser.h"
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/file_utils.h"
+#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/base/string_writer.h"
+
+namespace perfetto {
+namespace profiling {
+
+namespace {
+
+bool SymbolComparator(const uint64_t i, const BreakpadParser::Symbol& sym) {
+ return i < sym.start_address;
+}
+
+base::Optional<std::string> GetFileContents(const std::string& file_path) {
+ std::string file_contents;
+ base::ScopedFile fd = base::OpenFile(file_path, O_RDONLY);
+ // Read the contents of the file into |file_contents|.
+ if (!fd) {
+ return base::nullopt;
+ }
+ if (!base::ReadFileDescriptor(fd.get(), &file_contents)) {
+ return base::nullopt;
+ }
+
+ return base::make_optional(std::move(file_contents));
+}
+
+// Parses the given string and determines if it begins with the label
+// 'MODULE'. Returns an ok status if it does begin with this label and a fail
+// status otherwise.
+base::Status ParseIfModuleRecord(base::StringView first_line) {
+ // Split the given line by spaces.
+ const char kModuleLabel[] = "MODULE";
+ // Check to see if the line starts with 'MODULE'.
+ if (!base::StartsWith(first_line.ToStdString(), kModuleLabel)) {
+ return base::Status("Breakpad file not formatted correctly.");
+ }
+ return base::OkStatus();
+}
+
+} // namespace
+
+BreakpadParser::BreakpadParser(const std::string& file_path)
+ : file_path_(file_path) {}
+
+bool BreakpadParser::ParseFile() {
+ base::Optional<std::string> file_contents = GetFileContents(file_path_);
+ if (!file_contents) {
+ PERFETTO_ELOG("Could not get file contents of %s.", file_path_.c_str());
+ return false;
+ }
+
+ // TODO(uwemwilson): Extract a build id and store it in the Symbol object.
+
+ if (!ParseFromString(*file_contents)) {
+ PERFETTO_ELOG("Could not parse file contents.");
+ return false;
+ }
+
+ return true;
+}
+
+bool BreakpadParser::ParseFromString(const std::string& file_contents) {
+ // Create StringSplitter objects for each line so that specific lines can be
+ // used to create StringSplitter objects for words on that line.
+ base::StringSplitter lines(file_contents, '\n');
+ if (!lines.Next()) {
+ // File must be empty, so just return true and continue.
+ return true;
+ }
+
+ // TODO(crbug/1239750): Extract a build id and store it in the Symbol object.
+ base::StringView first_line(lines.cur_token(), lines.cur_token_size());
+ base::Status parse_record_status = ParseIfModuleRecord(first_line);
+ if (!parse_record_status.ok()) {
+ PERFETTO_ELOG("%s Breakpad files should begin with a MODULE record",
+ parse_record_status.message().c_str());
+ return false;
+ }
+
+ // Parse each line.
+ while (lines.Next()) {
+ parse_record_status = ParseIfFuncRecord(lines.cur_token());
+ if (!parse_record_status.ok()) {
+ PERFETTO_ELOG("%s", parse_record_status.message().c_str());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+base::Optional<std::string> BreakpadParser::GetSymbol(uint64_t address) const {
+ // Returns an iterator pointing to the first element where the symbol's start
+ // address is greater than |address|.
+ auto it = std::upper_bound(symbols_.begin(), symbols_.end(), address,
+ &SymbolComparator);
+ // If the first symbol's address is greater than |address| then |address| is
+ // too low to appear in |symbols_|.
+ if (it == symbols_.begin()) {
+ return base::nullopt;
+ }
+ // upper_bound() returns the first symbol who's start address is greater than
+ // |address|. Therefore to find the symbol with a range of addresses that
+ // |address| falls into, we check the previous symbol.
+ it--;
+ // Check to see if the address is in the function's range.
+ if (address >= it->start_address &&
+ address < it->start_address + it->function_size) {
+ return it->symbol_name;
+ }
+ return base::nullopt;
+}
+
+base::Status BreakpadParser::ParseIfFuncRecord(base::StringView current_line) {
+ // Parses a FUNC record from a file. Structure of a FUNC record:
+ // FUNC [m] address size parameter_size name
+ // m: The m field is optional. If present it indicates that multiple symbols
+ // reference this function's instructions. (In which case, only one symbol
+ // name is mentioned within the breakpad file.)
+ // address: The start address of the function relative to the module's load
+ // address.
+ // size: The length in bytes of function's instructions.
+ // parameter_size: A hexadecimal number indicating the size, in bytes, of the
+ // arguments pushed on the stack for this function.
+ // name: The function name. This field may contain spaces.
+ // More info at
+ // https://chromium.googlesource.com/breakpad/breakpad/+/HEAD/docs/symbol_files.md
+
+ const char kFuncLabel[] = "FUNC";
+ base::StringSplitter words(current_line.ToStdString(), ' ');
+ // Check to see if the first word indicates a FUNC record. If it is, create a
+ // Symbol struct and add tokens from words. If it isn't the function can just
+ // return true and resume parsing file.
+ if (!words.Next() || strcmp(words.cur_token(), kFuncLabel) != 0) {
+ return base::OkStatus();
+ }
+
+ Symbol new_symbol;
+ // There can be either 4 or 5 FUNC record tokens. The second token, 'm' is
+ // optional.
+ const char kOptionalArg[] = "m";
+ // Get the first argument on the line.
+ words.Next();
+
+ // If the optional argument is present, skip to the next token.
+ if (strcmp(words.cur_token(), kOptionalArg) == 0) {
+ words.Next();
+ }
+
+ // Get the start address.
+ base::Optional<uint64_t> optional_address =
+ base::CStringToUInt64(words.cur_token(), 16);
+ if (!optional_address) {
+ return base::Status("Address should be hexadecimal.");
+ }
+ new_symbol.start_address = *optional_address;
+
+ // Get the function size.
+ words.Next();
+ base::Optional<size_t> optional_func_size =
+ base::CStringToUInt32(words.cur_token(), 16);
+ if (!optional_func_size) {
+ return base::Status("Function size should be hexadecimal.");
+ }
+ new_symbol.function_size = *optional_func_size;
+
+ // Skip the parameter size.
+ words.Next();
+
+ // Get the function name. Function names can have spaces, so any token is now
+ // considered a part of the function name and will be appended to the buffer
+ // in |func_name_writer|.
+ std::unique_ptr<char[]> joined_string(new char[current_line.size()]);
+ base::StringWriter func_name_writer(joined_string.get(), current_line.size());
+ bool first_token = true;
+ while (words.Next()) {
+ if (!first_token) {
+ func_name_writer.AppendChar(' ');
+ } else {
+ first_token = false;
+ }
+ func_name_writer.AppendString(words.cur_token(), strlen(words.cur_token()));
+ }
+
+ new_symbol.symbol_name = func_name_writer.GetStringView().ToStdString();
+
+ symbols_.push_back(std::move(new_symbol));
+
+ return base::OkStatus();
+}
+
+} // namespace profiling
+} // namespace perfetto
diff --git a/src/profiling/symbolizer/breakpad_parser.h b/src/profiling/symbolizer/breakpad_parser.h
new file mode 100644
index 0000000..0377353
--- /dev/null
+++ b/src/profiling/symbolizer/breakpad_parser.h
@@ -0,0 +1,85 @@
+/*
+ * 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_SYMBOLIZER_BREAKPAD_PARSER_H_
+#define SRC_PROFILING_SYMBOLIZER_BREAKPAD_PARSER_H_
+
+#include <string>
+#include <vector>
+
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/optional.h"
+#include "perfetto/ext/base/string_view.h"
+
+namespace perfetto {
+namespace profiling {
+
+// The BreakpadParser class is used to parse a breakpad file and store data on
+// symbols so that a given address can be used to query a symbol. The class is
+// instantiated with the |file_path| of the file to be parsed. Breakpad file
+// format:
+// https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
+// Usage:
+//
+// BreakpadParser parser("file.breakpad");
+// parser.ParseFile();
+// std::string symbol = parser.GetSymbol(addr);
+class BreakpadParser {
+ public:
+ struct Symbol {
+ // The address where a function starts.
+ uint64_t start_address = 0;
+ // The length in bytes of the function's instructions.
+ size_t function_size = 0;
+ // The human-readable name for the function signature.
+ std::string symbol_name;
+ };
+
+ explicit BreakpadParser(const std::string& file_path);
+
+ BreakpadParser(const BreakpadParser& other) = delete;
+ BreakpadParser& operator=(const BreakpadParser& other) = delete;
+
+ // Fills in |symbols_| by parsing the breakpad file given.
+ // Returns true if it is able to parse the entire file specified by
+ // |file_path_|. Returns false if the parsing fails.
+ bool ParseFile();
+
+ // Parses from a string instead of a file.
+ bool ParseFromString(const std::string& file_contents);
+
+ // Returns the function name corresponding to |address| as a string. The
+ // search is log(N) on the number of functions in the binary. |address| is the
+ // relative offset from the start of the binary.
+ base::Optional<std::string> GetSymbol(uint64_t address) const;
+
+ const std::vector<Symbol>& symbols_for_testing() const { return symbols_; }
+
+ private:
+ // Parses the given string and creates a new Symbol object if it is a FUNC
+ // record. Returns an ok status if it was successfully able to add to the
+ // |symbols_| or if the string is not a FUNC record. Return a fail status on
+ // parsing errors on FUNC record.
+ base::Status ParseIfFuncRecord(base::StringView current_line);
+
+ std::vector<Symbol> symbols_;
+ const std::string file_path_;
+};
+
+} // namespace profiling
+} // namespace perfetto
+
+#endif // SRC_PROFILING_SYMBOLIZER_BREAKPAD_PARSER_H_
diff --git a/src/profiling/symbolizer/breakpad_parser_unittest.cc b/src/profiling/symbolizer/breakpad_parser_unittest.cc
new file mode 100644
index 0000000..d42b6da
--- /dev/null
+++ b/src/profiling/symbolizer/breakpad_parser_unittest.cc
@@ -0,0 +1,214 @@
+/*
+ * 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/profiling/symbolizer/breakpad_parser.h"
+
+namespace perfetto {
+namespace profiling {
+
+namespace {
+
+// Used to initialize parser objects.
+constexpr char kFakeFilePath[] = "bad/file/path";
+
+TEST(BreakpadParserTest, FileIsEmpty) {
+ base::TempFile file = base::TempFile::Create();
+ BreakpadParser parser(file.path());
+ ASSERT_TRUE(parser.ParseFile());
+ EXPECT_TRUE(parser.symbols_for_testing().empty());
+}
+
+TEST(BreakpadParserTest, FileNotOpened) {
+ BreakpadParser parser(kFakeFilePath);
+ ASSERT_FALSE(parser.ParseFile());
+ EXPECT_TRUE(parser.symbols_for_testing().empty());
+}
+
+TEST(BreakpadParserTest, ContainsNoFuncRecord) {
+ BreakpadParser parser(kFakeFilePath);
+ constexpr char kTestFileContents[] =
+ "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
+ "FILE 0 /Applications/../MacOSX10.10.sdk/usr/include/ctype.h\n"
+ "1031 2 39 4\n"
+ "PUBLIC 313c0 0 items\n"
+ "STACK CFI 1014 .cfa: $rbp 16 +\n";
+ ASSERT_TRUE(parser.ParseFromString(kTestFileContents));
+ EXPECT_TRUE(parser.symbols_for_testing().empty());
+}
+
+TEST(BreakpadParserTest, ContainsOneFuncRecord) {
+ BreakpadParser parser(kFakeFilePath);
+ constexpr char kTestFileContents[] =
+ "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
+ "FUNC 1010 23 0 foo::bar()\n"
+ "1031 2 39 4\n"
+ "PUBLIC 2e7c0 0 items\n";
+ ASSERT_TRUE(parser.ParseFromString(kTestFileContents));
+ ASSERT_EQ(parser.symbols_for_testing().size(), 1u);
+ EXPECT_STREQ(parser.symbols_for_testing()[0].symbol_name.c_str(),
+ "foo::bar()");
+ EXPECT_EQ(parser.symbols_for_testing()[0].start_address,
+ static_cast<uint64_t>(0x1010));
+}
+
+TEST(BreakpadParserTest, ContainsManyFuncRecords) {
+ BreakpadParser parser(kFakeFilePath);
+ constexpr char kTestFileContents[] =
+ "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
+ "FUNC 1010 23 0 foo_foo\n"
+ "1031 2 39 4\n"
+ "FUNC 1040 84 0 bar_1\n"
+ "1040 4 44 5\n"
+ "FUNC 10d0 6b 0 baz_baz()\n";
+ ASSERT_TRUE(parser.ParseFromString(kTestFileContents));
+ ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
+ EXPECT_STREQ(parser.symbols_for_testing()[0].symbol_name.c_str(), "foo_foo");
+ EXPECT_EQ(parser.symbols_for_testing()[0].start_address,
+ static_cast<uint64_t>(0x1010));
+ EXPECT_EQ(parser.symbols_for_testing()[0].function_size, 35u);
+ EXPECT_STREQ(parser.symbols_for_testing()[1].symbol_name.c_str(), "bar_1");
+ EXPECT_EQ(parser.symbols_for_testing()[1].start_address,
+ static_cast<uint64_t>(0x1040));
+ EXPECT_EQ(parser.symbols_for_testing()[1].function_size, 132u);
+ EXPECT_STREQ(parser.symbols_for_testing()[2].symbol_name.c_str(),
+ "baz_baz()");
+ EXPECT_EQ(parser.symbols_for_testing()[2].start_address,
+ static_cast<uint64_t>(0x10d0));
+ EXPECT_EQ(parser.symbols_for_testing()[2].function_size, 107u);
+}
+
+TEST(BreakpadParserTest, OptionalArgument) {
+ BreakpadParser parser(kFakeFilePath);
+ constexpr char kTestFileContents[] =
+ "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
+ "FUNC m 1010 23 0 foo_foo()\n"
+ "1031 2 39 4\n"
+ "FUNC m 1040 84 0 bar_1\n";
+ ASSERT_TRUE(parser.ParseFromString(kTestFileContents));
+ ASSERT_EQ(parser.symbols_for_testing().size(), 2u);
+ EXPECT_STREQ(parser.symbols_for_testing()[0].symbol_name.c_str(),
+ "foo_foo()");
+ EXPECT_EQ(parser.symbols_for_testing()[0].start_address,
+ static_cast<uint64_t>(0x1010));
+ EXPECT_STREQ(parser.symbols_for_testing()[1].symbol_name.c_str(), "bar_1");
+ EXPECT_EQ(parser.symbols_for_testing()[1].start_address,
+ static_cast<uint64_t>(0x1040));
+}
+
+TEST(BreakpadParserTest, FuncNameWithSpaces) {
+ BreakpadParser parser(kFakeFilePath);
+ constexpr char kTestFileContents[] =
+ "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
+ "FUNC 1010 23 0 foo foo foo\n"
+ "1031 2 39 4\n"
+ "FUNC 1040 84 0 bar\n"
+ "1040 4 44 5\n"
+ "FUNC 10d0 6b 0 baz\n";
+ ASSERT_TRUE(parser.ParseFromString(kTestFileContents));
+ ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
+ EXPECT_STREQ(parser.symbols_for_testing()[0].symbol_name.c_str(),
+ "foo foo foo");
+ EXPECT_EQ(parser.symbols_for_testing()[0].start_address,
+ static_cast<uint64_t>(0x1010));
+ EXPECT_STREQ(parser.symbols_for_testing()[2].symbol_name.c_str(), "baz");
+ EXPECT_EQ(parser.symbols_for_testing()[2].start_address,
+ static_cast<uint64_t>(0x10d0));
+}
+
+TEST(BreakpadParserTest, NonHexAddress) {
+ BreakpadParser parser(kFakeFilePath);
+ constexpr char kTestFileContents[] =
+ "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
+ "FUNC foo 23 0 foo\n"
+ "1031 2 39 4\n"
+ "FUNC 1040 84 0 bar\n"
+ "1040 4 44 5\n"
+ "FUNC 10d0 6b 0 baz\n";
+ ASSERT_FALSE(parser.ParseFromString(kTestFileContents));
+ EXPECT_TRUE(parser.symbols_for_testing().empty());
+}
+
+TEST(BreakpadParserTest, NoModuleRecord) {
+ BreakpadParser parser(kFakeFilePath);
+ constexpr char kTestFileContents[] =
+ "FUNC foo 23 0 foo()\n"
+ "1031 2 39 4\n"
+ "FUNC 1040 84 0 bar\n"
+ "1040 4 44 5\n"
+ "FUNC 10d0 6b 0 baz\n";
+ ASSERT_FALSE(parser.ParseFromString(kTestFileContents));
+ EXPECT_TRUE(parser.symbols_for_testing().empty());
+}
+
+// To make it easy to read, each FUNC record is followed by two LINE records:
+// one showing the start address of the ending instruction and one showing the
+// address where the function ends.
+constexpr char kGetSymbolTestContents[] =
+ "MODULE mac x86_64 E3A0F28FBCB43C15986D8608AF1DD2380 exif.so\n"
+ "FUNC 1010 23 0 foo\n"
+ "1031 2 39 4\n"
+ "1033 0 0 0\n"
+ "FUNC 1040 84 0 bar\n"
+ "10b6 e 44 5\n"
+ "10c4 0 0 0\n"
+ "FUNC 10d0 6b 0 baz\n"
+ "1136 5 44 5\n"
+ "113b 0 0 0\n";
+
+TEST(BreakpadParserTest, GivenStartAddr) {
+ BreakpadParser parser(kFakeFilePath);
+ ASSERT_TRUE(parser.ParseFromString(kGetSymbolTestContents));
+ ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
+ EXPECT_EQ(*parser.GetSymbol(0x1010U), "foo");
+ EXPECT_EQ(*parser.GetSymbol(0x10d0U), "baz");
+}
+
+TEST(BreakpadParserTest, GivenAddrInRange) {
+ BreakpadParser parser(kFakeFilePath);
+ ASSERT_TRUE(parser.ParseFromString(kGetSymbolTestContents));
+ ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
+ EXPECT_EQ(*parser.GetSymbol(0x1030U), "foo");
+ EXPECT_EQ(*parser.GetSymbol(0x10c0U), "bar");
+}
+
+TEST(BreakpadParserTest, AddrTooLow) {
+ BreakpadParser parser(kFakeFilePath);
+ ASSERT_TRUE(parser.ParseFromString(kGetSymbolTestContents));
+ ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
+ EXPECT_FALSE(parser.GetSymbol(0x1000U));
+}
+
+TEST(BreakpadParserTest, AddrTooHigh) {
+ BreakpadParser parser(kFakeFilePath);
+ ASSERT_TRUE(parser.ParseFromString(kGetSymbolTestContents));
+ ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
+ EXPECT_FALSE(parser.GetSymbol(0x3000U));
+}
+
+TEST(BreakpadParserTest, AddrBetweenFunctions) {
+ BreakpadParser parser(kFakeFilePath);
+ ASSERT_TRUE(parser.ParseFromString(kGetSymbolTestContents));
+ ASSERT_EQ(parser.symbols_for_testing().size(), 3u);
+ EXPECT_FALSE(parser.GetSymbol(0x1036U));
+}
+
+} // namespace
+} // namespace profiling
+} // namespace perfetto
diff --git a/src/profiling/symbolizer/breakpad_symbolizer.cc b/src/profiling/symbolizer/breakpad_symbolizer.cc
new file mode 100644
index 0000000..c7558c7
--- /dev/null
+++ b/src/profiling/symbolizer/breakpad_symbolizer.cc
@@ -0,0 +1,99 @@
+/*
+ * 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/profiling/symbolizer/breakpad_symbolizer.h"
+
+#include "perfetto/base/build_config.h"
+#include "perfetto/ext/base/file_utils.h"
+#include "perfetto/ext/base/optional.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/string_writer.h"
+#include "src/profiling/symbolizer/breakpad_parser.h"
+
+namespace perfetto {
+namespace profiling {
+
+namespace {
+
+// Returns the file path for a breakpad symbol file with the given |build_id|.
+std::string MakeFilePath(const std::string& build_id,
+ const std::string& symbol_dir_path) {
+ // The directory of the symbol file is stored in an environment variable.
+ constexpr char kBreakpadSuffix[] = ".breakpad";
+ std::string file_path;
+ // Append file name to symbol directory path using |build_id| and
+ // |kBreakpadSuffix|.
+ file_path.append(symbol_dir_path);
+// TODO: Add a path utility for perfetto to use here.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ file_path.append("\\");
+#else
+ file_path.append("/");
+#endif
+ file_path.append(build_id);
+ file_path.append(kBreakpadSuffix);
+
+ return file_path;
+}
+
+} // namespace
+
+BreakpadSymbolizer::BreakpadSymbolizer(const std::string& symbol_dir_path)
+ : symbol_dir_path_(symbol_dir_path) {}
+
+std::vector<std::vector<SymbolizedFrame>> BreakpadSymbolizer::Symbolize(
+ const std::string&,
+ const std::string& build_id,
+ uint64_t,
+ const std::vector<uint64_t>& address) {
+ std::vector<std::vector<SymbolizedFrame>> result;
+ size_t num_symbolized_frames = 0;
+ result.reserve(address.size());
+ std::string file_path;
+
+ // Check to see if the |file_path_for_testing_| member is populated. If it is,
+ // this file must be used.
+ if (file_path_for_testing_.empty()) {
+ file_path = MakeFilePath(build_id, symbol_dir_path_).c_str();
+ } else {
+ file_path = file_path_for_testing_;
+ }
+
+ BreakpadParser parser(file_path);
+ if (!parser.ParseFile()) {
+ PERFETTO_ELOG("Failed to parse file %s.", file_path.c_str());
+ PERFETTO_PLOG("Symbolized %zu of %zu frames.", num_symbolized_frames,
+ address.size());
+ return result;
+ }
+
+ // Add each address's function name to the |result| vector in the same order.
+ for (uint64_t addr : address) {
+ SymbolizedFrame frame;
+ base::Optional<std::string> opt_func_name = parser.GetSymbol(addr);
+ if (opt_func_name) {
+ frame.function_name = *opt_func_name;
+ num_symbolized_frames++;
+ }
+ result.push_back({std::move(frame)});
+ }
+ PERFETTO_PLOG("Symbolized %zu of %zu frames.", num_symbolized_frames,
+ address.size());
+ return result;
+}
+
+} // namespace profiling
+} // namespace perfetto
diff --git a/src/profiling/symbolizer/breakpad_symbolizer.h b/src/profiling/symbolizer/breakpad_symbolizer.h
new file mode 100644
index 0000000..89c5ec5
--- /dev/null
+++ b/src/profiling/symbolizer/breakpad_symbolizer.h
@@ -0,0 +1,60 @@
+/*
+ * 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_SYMBOLIZER_BREAKPAD_SYMBOLIZER_H_
+#define SRC_PROFILING_SYMBOLIZER_BREAKPAD_SYMBOLIZER_H_
+
+#include "perfetto/ext/base/string_view.h"
+#include "src/profiling/symbolizer/symbolizer.h"
+
+namespace perfetto {
+namespace profiling {
+
+// A subclass of Symbolizer that overrides the Symbolize method to make the
+// symbolization process work for breakpad files.
+class BreakpadSymbolizer : public Symbolizer {
+ public:
+ // Takes the path to a folder containing breakpad symbol files as an argument.
+ // The files in this folder will be used to symbolize a given trace. Each
+ // breakpad symbol file should use the upper case hex representation of the
+ // module ID, contained in the first line of the file, as the name of the
+ // file, with a ".breakpad" suffix. eg: <module_id>.breakpad.
+ explicit BreakpadSymbolizer(const std::string& symbol_dir_path);
+
+ BreakpadSymbolizer(BreakpadSymbolizer&& other) = default;
+ BreakpadSymbolizer& operator=(BreakpadSymbolizer&& other) = default;
+
+ std::vector<std::vector<SymbolizedFrame>> Symbolize(
+ const std::string&,
+ const std::string& build_id,
+ uint64_t,
+ const std::vector<uint64_t>& address) override;
+
+ void SetBreakpadFileForTesting(const std::string& path) {
+ file_path_for_testing_ = path;
+ }
+
+ bool BuildIdNeedsHexConversion() override { return false; }
+
+ private:
+ std::string symbol_dir_path_;
+ std::string file_path_for_testing_;
+};
+
+} // namespace profiling
+} // namespace perfetto
+
+#endif // SRC_PROFILING_SYMBOLIZER_BREAKPAD_SYMBOLIZER_H_
diff --git a/src/profiling/symbolizer/breakpad_symbolizer_unittest.cc b/src/profiling/symbolizer/breakpad_symbolizer_unittest.cc
new file mode 100644
index 0000000..ed68f88
--- /dev/null
+++ b/src/profiling/symbolizer/breakpad_symbolizer_unittest.cc
@@ -0,0 +1,90 @@
+/*
+ * 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 <stdlib.h>
+
+#include "test/gtest_and_gmock.h"
+
+#include "perfetto/ext/base/file_utils.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/temp_file.h"
+#include "src/profiling/symbolizer/breakpad_symbolizer.h"
+
+namespace perfetto {
+namespace profiling {
+
+namespace {
+
+TEST(BreakpadSymbolizerTest, NonExistantFile) {
+ const std::string kBadFilePath = "/bad/file/path";
+ constexpr char kTestDir[] = "Unused";
+ BreakpadSymbolizer symbolizer(kTestDir);
+ symbolizer.SetBreakpadFileForTesting(kBadFilePath);
+ std::vector<uint64_t> addresses = {0x1010u, 0x1040u, 0x10d0u, 0x1140u};
+ std::vector<std::vector<SymbolizedFrame>> frames =
+ symbolizer.Symbolize("mapping", "build", 0, addresses);
+ EXPECT_TRUE(frames.empty());
+}
+
+// To make it easy to read, each FUNC record is followed by two LINE records:
+// one showing the start address of the ending instruction and one showing the
+// address where the function ends.
+constexpr char kTestFileContents[] =
+ "MODULE mac x86_64 A68BC89F12C foo.so\n"
+ "FUNC 1010 23 0 foo_foo()\n"
+ "1031 2 39 4\n"
+ "1033 0 0 0\n"
+ "FUNC 1040 84 0 bar_bar_bar()\n"
+ "10b6 e 44 5\n"
+ "10c4 0 0 0\n"
+ "FUNC 10d0 6b 0 foo::bar()\n"
+ "1136 5 44 5\n"
+ "113b 0 0 0\n"
+ "FUNC 1140 6b 0 baz()\n"
+ "114a 2 82 5\n"
+ "114c 0 0 0\n";
+constexpr ssize_t kTestFileLength = base::ArraySize(kTestFileContents);
+
+TEST(BreakpadSymbolizerTest, SymbolFrames) {
+ base::TempFile test_file = base::TempFile::Create();
+ ASSERT_TRUE(*test_file);
+ ssize_t written =
+ base::WriteAll(test_file.fd(), kTestFileContents, kTestFileLength);
+ ASSERT_EQ(written, kTestFileLength);
+ constexpr char kTestDir[] = "Unused";
+ BreakpadSymbolizer symbolizer(kTestDir);
+ symbolizer.SetBreakpadFileForTesting(test_file.path());
+ // The first 4 addresses are valid, while the last four, cannot be mapped to a
+ // function because they are either too low, too large, or not mapped in any
+ // function's range.
+ std::vector<uint64_t> addresses = {0x1010u, 0x1040u, 0x10d0u, 0x1140u,
+ 0xeu, 0x1036u, 0x30d0u, 0x113eu};
+ std::vector<std::vector<SymbolizedFrame>> frames =
+ symbolizer.Symbolize("mapping", "build", 0, addresses);
+ ASSERT_EQ(frames.size(), 8u);
+ EXPECT_EQ(frames[0][0].function_name, "foo_foo()");
+ EXPECT_EQ(frames[1][0].function_name, "bar_bar_bar()");
+ EXPECT_EQ(frames[2][0].function_name, "foo::bar()");
+ EXPECT_EQ(frames[3][0].function_name, "baz()");
+ EXPECT_TRUE(frames[4][0].function_name.empty());
+ EXPECT_TRUE(frames[5][0].function_name.empty());
+ EXPECT_TRUE(frames[6][0].function_name.empty());
+ EXPECT_TRUE(frames[7][0].function_name.empty());
+}
+
+} // namespace
+} // namespace profiling
+} // namespace perfetto
diff --git a/src/profiling/symbolizer/elf.h b/src/profiling/symbolizer/elf.h
new file mode 100644
index 0000000..de03612
--- /dev/null
+++ b/src/profiling/symbolizer/elf.h
@@ -0,0 +1,172 @@
+/*
+ * 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_SYMBOLIZER_ELF_H_
+#define SRC_PROFILING_SYMBOLIZER_ELF_H_
+
+#include <stddef.h>
+#include <cinttypes>
+
+#include "perfetto/base/build_config.h"
+
+// 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.
+
+namespace perfetto {
+namespace profiling {
+
+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 ELFDATA2LSB = 1;
+constexpr auto EV_CURRENT = 1;
+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;
+constexpr auto EI_DATA = 5;
+constexpr auto EI_VERSION = 6;
+
+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;
+ };
+};
+
+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;
+ };
+};
+
+template <typename E>
+typename E::Shdr* GetShdr(void* mem, const typename E::Ehdr* ehdr, size_t i) {
+ return reinterpret_cast<typename E::Shdr*>(
+ static_cast<char*>(mem) + ehdr->e_shoff + i * sizeof(typename E::Shdr));
+}
+
+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));
+}
+
+} // namespace profiling
+} // namespace perfetto
+
+#endif // SRC_PROFILING_SYMBOLIZER_ELF_H_
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..bcacb37 100644
--- a/src/profiling/symbolizer/local_symbolizer.cc
+++ b/src/profiling/symbolizer/local_symbolizer.cc
@@ -18,6 +18,7 @@
#include <fcntl.h>
+#include <cinttypes>
#include <memory>
#include <sstream>
#include <string>
@@ -30,7 +31,7 @@
#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/elf.h"
#include "src/profiling/symbolizer/scoped_read_mmap.h"
namespace perfetto {
@@ -69,7 +70,6 @@
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/utils.h"
-#include <inttypes.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -116,142 +116,6 @@
}
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;
- };
-};
-
-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;
- };
-};
-
-template <typename E>
-typename E::Shdr* GetShdr(void* mem, const typename E::Ehdr* ehdr, size_t i) {
- return reinterpret_cast<typename E::Shdr*>(
- static_cast<char*>(mem) + ehdr->e_shoff + i * sizeof(typename E::Shdr));
-}
-
-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,
@@ -352,31 +216,36 @@
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)
+base::Optional<BuildIdAndLoadBias> GetBuildIdAndLoadBias(
+ const std::string& fname) {
+ base::Optional<size_t> size = base::GetFileSize(fname);
+ if (!size.has_value()) {
+ PERFETTO_PLOG("Failed to get file size %s", fname.c_str());
return base::nullopt;
- ScopedReadMmap map(fname, size);
+ }
+ static_assert(EI_CLASS > EI_MAG3, "mem[EI_MAG?] accesses are in range.");
+ if (*size <= EI_CLASS)
+ return base::nullopt;
+ ScopedReadMmap map(fname.c_str(), *size);
if (!map.IsValid()) {
PERFETTO_PLOG("mmap");
return base::nullopt;
}
char* mem = static_cast<char*>(*map);
- if (!IsElf(mem, size))
+ 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);
+ 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);
+ build_id = GetBuildId<Elf64>(mem, *size);
+ load_bias = GetLoadBias<Elf64>(mem, *size);
break;
default:
return base::nullopt;
@@ -387,35 +256,48 @@
return base::nullopt;
}
+bool StartsWithElfMagic(const std::string& fname) {
+ base::ScopedFile fd(base::OpenFile(fname, O_RDONLY));
+ char magic[EI_MAG3 + 1];
+ if (!fd) {
+ PERFETTO_PLOG("Failed to open %s", fname.c_str());
+ return false;
+ }
+ ssize_t rd = base::Read(*fd, &magic, sizeof(magic));
+ if (rd != sizeof(magic)) {
+ PERFETTO_PLOG("Failed to read %s", fname.c_str());
+ return false;
+ }
+ if (!IsElf(magic, static_cast<size_t>(rd))) {
+ PERFETTO_DLOG("%s not an ELF.", fname.c_str());
+ return false;
+ }
+ return true;
+}
+
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;
+ for (const std::string& dir : dirs) {
+ std::vector<std::string> files;
+ base::Status status = base::ListFilesRecursive(dir, files);
+ if (!status.ok()) {
+ PERFETTO_PLOG("Failed to list directory %s", dir.c_str());
+ continue;
+ }
+ for (const std::string& basename : files) {
+ std::string fname = dir + "/" + basename;
+ if (!StartsWithElfMagic(fname)) {
+ continue;
}
- 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);
+ if (build_id_and_load_bias) {
+ result.emplace(build_id_and_load_bias->build_id,
+ FoundBinary{fname, build_id_and_load_bias->load_bias});
}
}
- 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;
}
@@ -486,15 +368,8 @@
if (!base::FileExists(symbol_file)) {
return base::nullopt;
}
- // Openfile opens the file with an exclusive lock on windows.
- size_t size = GetFileSize(symbol_file);
-
- if (size == 0) {
- return base::nullopt;
- }
-
base::Optional<BuildIdAndLoadBias> build_id_and_load_bias =
- GetBuildIdAndLoadBias(symbol_file.c_str(), size);
+ GetBuildIdAndLoadBias(symbol_file);
if (!build_id_and_load_bias)
return base::nullopt;
if (build_id_and_load_bias->build_id != build_id) {
diff --git a/src/profiling/symbolizer/local_symbolizer.h b/src/profiling/symbolizer/local_symbolizer.h
index 01d1fe4..bb8b0c2 100644
--- a/src/profiling/symbolizer/local_symbolizer.h
+++ b/src/profiling/symbolizer/local_symbolizer.h
@@ -107,6 +107,8 @@
uint64_t load_bias,
const std::vector<uint64_t>& address) override;
+ bool BuildIdNeedsHexConversion() override { return true; }
+
~LocalSymbolizer() override;
private:
diff --git a/src/profiling/symbolizer/local_symbolizer_unittest.cc b/src/profiling/symbolizer/local_symbolizer_unittest.cc
index b96d318..921c878 100644
--- a/src/profiling/symbolizer/local_symbolizer_unittest.cc
+++ b/src/profiling/symbolizer/local_symbolizer_unittest.cc
@@ -20,7 +20,11 @@
// This translation unit is built only on Linux and MacOS. See //gn/BUILD.gn.
#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
+#include <cstddef>
+
+#include "src/base/test/tmp_dir_tree.h"
#include "src/base/test/utils.h"
+#include "src/profiling/symbolizer/elf.h"
#include "src/profiling/symbolizer/local_symbolizer.h"
#include "src/profiling/symbolizer/subprocess.h"
@@ -95,6 +99,69 @@
}
}
+// Creates a very simple ELF file content with the first 20 bytes of `build_id`
+// as build id (if build id is shorter the remainin bytes are zero).
+std::string CreateElfWithBuildId(const std::string& build_id) {
+ struct SimpleElf {
+ Elf64::Ehdr ehdr;
+ Elf64::Shdr shdr;
+ Elf64::Nhdr nhdr;
+ char note_name[4];
+ char note_desc[20];
+ } e;
+ memset(&e, 0, sizeof e);
+
+ e.ehdr.e_ident[EI_MAG0] = ELFMAG0;
+ e.ehdr.e_ident[EI_MAG1] = ELFMAG1;
+ e.ehdr.e_ident[EI_MAG2] = ELFMAG2;
+ e.ehdr.e_ident[EI_MAG3] = ELFMAG3;
+ e.ehdr.e_ident[EI_CLASS] = ELFCLASS64;
+ e.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+ e.ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+ e.ehdr.e_version = EV_CURRENT;
+ e.ehdr.e_shentsize = sizeof(Elf64::Shdr);
+ e.ehdr.e_shnum = 1;
+ e.ehdr.e_ehsize = sizeof e.ehdr;
+ e.ehdr.e_shoff = offsetof(SimpleElf, shdr);
+
+ e.shdr.sh_type = SHT_NOTE;
+ e.shdr.sh_offset = offsetof(SimpleElf, nhdr);
+
+ e.nhdr.n_type = NT_GNU_BUILD_ID;
+ e.nhdr.n_namesz = sizeof e.note_name;
+ e.nhdr.n_descsz = sizeof e.note_desc;
+ strcpy(e.note_name, "GNU");
+ memcpy(e.note_desc, build_id.c_str(),
+ std::min(build_id.size(), sizeof(e.note_desc)));
+
+ e.shdr.sh_size = offsetof(SimpleElf, note_desc) + sizeof(e.note_desc) -
+ offsetof(SimpleElf, nhdr);
+
+ return std::string(reinterpret_cast<const char*>(&e), sizeof e);
+}
+
+TEST(LocalBinaryIndexerTest, SimpleTree) {
+ base::TmpDirTree tmp;
+ tmp.AddDir("dir1");
+ tmp.AddFile("dir1/elf1", CreateElfWithBuildId("AAAAAAAAAAAAAAAAAAAA"));
+ tmp.AddFile("dir1/nonelf1", "OTHERDATA");
+ tmp.AddDir("dir2");
+ tmp.AddFile("dir2/elf1", CreateElfWithBuildId("BBBBBBBBBBBBBBBBBBBB"));
+ tmp.AddFile("dir2/nonelf1", "other text");
+
+ LocalBinaryIndexer indexer({tmp.path() + "/dir1", tmp.path() + "/dir2"});
+
+ base::Optional<FoundBinary> bin1 =
+ indexer.FindBinary("", "AAAAAAAAAAAAAAAAAAAA");
+ ASSERT_TRUE(bin1.has_value());
+ EXPECT_EQ(bin1.value().file_name, tmp.path() + "/dir1/elf1");
+
+ base::Optional<FoundBinary> bin2 =
+ indexer.FindBinary("", "BBBBBBBBBBBBBBBBBBBB");
+ ASSERT_TRUE(bin2.has_value());
+ EXPECT_EQ(bin2.value().file_name, tmp.path() + "/dir2/elf1");
+}
+
} // namespace
} // namespace profiling
} // namespace perfetto
diff --git a/src/profiling/symbolizer/symbolize_database.cc b/src/profiling/symbolizer/symbolize_database.cc
index a002aea..c6fca90 100644
--- a/src/profiling/symbolizer/symbolize_database.cc
+++ b/src/profiling/symbolizer/symbolize_database.cc
@@ -81,14 +81,20 @@
}
std::map<UnsymbolizedMapping, std::vector<uint64_t>> GetUnsymbolizedFrames(
- trace_processor::TraceProcessor* tp) {
+ trace_processor::TraceProcessor* tp,
+ bool convert_build_id_to_bytes) {
std::map<UnsymbolizedMapping, 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()),
+ std::string build_id;
+ if (convert_build_id_to_bytes) {
+ build_id = FromHex(it.Get(1).AsString());
+ } else {
+ build_id = it.Get(1).AsString();
+ }
+ UnsymbolizedMapping unsymbolized_mapping{it.Get(0).AsString(), build_id,
static_cast<uint64_t>(load_bias)};
int64_t rel_pc = it.Get(2).AsLong();
res[unsymbolized_mapping].emplace_back(rel_pc);
@@ -106,7 +112,8 @@
Symbolizer* symbolizer,
std::function<void(const std::string&)> callback) {
PERFETTO_CHECK(symbolizer);
- auto unsymbolized = GetUnsymbolizedFrames(tp);
+ auto unsymbolized =
+ GetUnsymbolizedFrames(tp, symbolizer->BuildIdNeedsHexConversion());
for (auto it = unsymbolized.cbegin(); it != unsymbolized.cend(); ++it) {
const auto& unsymbolized_mapping = it->first;
const std::vector<uint64_t>& rel_pcs = it->second;
diff --git a/src/profiling/symbolizer/symbolizer.h b/src/profiling/symbolizer/symbolizer.h
index 3e96142..85c3f91 100644
--- a/src/profiling/symbolizer/symbolizer.h
+++ b/src/profiling/symbolizer/symbolizer.h
@@ -27,7 +27,7 @@
struct SymbolizedFrame {
std::string function_name;
std::string file_name;
- uint32_t line;
+ uint32_t line = 0;
};
class Symbolizer {
@@ -43,6 +43,12 @@
uint64_t load_bias,
const std::vector<uint64_t>& address) = 0;
virtual ~Symbolizer();
+
+ // LocalSymbolizer uses a specific conversion of a symbol file's |build_id| to
+ // bytes, but BreakpadSymbolizer requires the |build_id| as given. Return true
+ // if the |build_id| passed to Symbolize() requires the conversion to bytes
+ // and false otherwise.
+ virtual bool BuildIdNeedsHexConversion() = 0;
};
} // namespace profiling
diff --git a/src/protozero/filtering/filter_util.h b/src/protozero/filtering/filter_util.h
index 3cc7655..14d01dc 100644
--- a/src/protozero/filtering/filter_util.h
+++ b/src/protozero/filtering/filter_util.h
@@ -23,11 +23,9 @@
#include <map>
#include <string>
-namespace google {
-namespace protobuf {
-class Descriptor;
-}
-} // namespace google
+// We include this intentionally instead of forward declaring to allow
+// for an easy find/replace transformation when moving to Google3.
+#include <google/protobuf/descriptor.h>
namespace protozero {
diff --git a/src/protozero/proto_decoder.cc b/src/protozero/proto_decoder.cc
index f83c91f..97ac429 100644
--- a/src/protozero/proto_decoder.cc
+++ b/src/protozero/proto_decoder.cc
@@ -17,7 +17,10 @@
#include "perfetto/protozero/proto_decoder.h"
#include <string.h>
+
+#include <cinttypes>
#include <limits>
+#include <memory>
#include "perfetto/base/compiler.h"
#include "perfetto/base/logging.h"
diff --git a/src/protozero/scattered_stream_writer.cc b/src/protozero/scattered_stream_writer.cc
index 16dd895..3487fb0 100644
--- a/src/protozero/scattered_stream_writer.cc
+++ b/src/protozero/scattered_stream_writer.cc
@@ -67,6 +67,15 @@
uint8_t* begin = write_ptr_;
write_ptr_ += size;
#if PERFETTO_DCHECK_IS_ON()
+ // In the past, the service had a matching DCHECK in
+ // TraceBuffer::TryPatchChunkContents, which was assuming that service and all
+ // producers are built with matching DCHECK levels. This turned out to be a
+ // source of problems and was removed in b/197340286. This memset is useless
+ // these days and is here only to maintain ABI compatibility between producers
+ // that use a v20+ SDK and older versions of the service that were built in
+ // debug mode. At some point around 2023 it should be safe to remove it.
+ // (running a debug version of traced in production seems a bad idea
+ // regardless).
memset(begin, 0, size);
#endif
return begin;
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 23625b3..c3e9935 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -88,6 +88,8 @@
"importers/proto/chrome_system_probes_module.h",
"importers/proto/chrome_system_probes_parser.cc",
"importers/proto/chrome_system_probes_parser.h",
+ "importers/proto/flamegraph_construction_algorithms.cc",
+ "importers/proto/flamegraph_construction_algorithms.h",
"importers/proto/heap_profile_tracker.cc",
"importers/proto/heap_profile_tracker.h",
"importers/proto/memory_tracker_snapshot_module.cc",
@@ -298,8 +300,8 @@
"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/descendant_generator.cc",
+ "dynamic/descendant_generator.h",
"dynamic/describe_slice_generator.cc",
"dynamic/describe_slice_generator.h",
"dynamic/experimental_annotated_stack_generator.cc",
@@ -308,6 +310,8 @@
"dynamic/experimental_counter_dur_generator.h",
"dynamic/experimental_flamegraph_generator.cc",
"dynamic/experimental_flamegraph_generator.h",
+ "dynamic/experimental_flat_slice_generator.cc",
+ "dynamic/experimental_flat_slice_generator.h",
"dynamic/experimental_sched_upid_generator.cc",
"dynamic/experimental_sched_upid_generator.h",
"dynamic/experimental_slice_layout_generator.cc",
@@ -443,6 +447,7 @@
if (enable_perfetto_trace_processor_sqlite) {
sources += [
"dynamic/experimental_counter_dur_generator_unittest.cc",
+ "dynamic/experimental_flat_slice_generator_unittest.cc",
"dynamic/experimental_slice_layout_generator_unittest.cc",
"dynamic/thread_state_generator_unittest.cc",
]
diff --git a/src/trace_processor/dynamic/ancestor_generator.cc b/src/trace_processor/dynamic/ancestor_generator.cc
index 3db6d3d..1e479bc 100644
--- a/src/trace_processor/dynamic/ancestor_generator.cc
+++ b/src/trace_processor/dynamic/ancestor_generator.cc
@@ -31,11 +31,25 @@
return context->storage->slice_table().GetColumnCount();
case AncestorGenerator::Ancestor::kStackProfileCallsite:
return context->storage->stack_profile_callsite_table().GetColumnCount();
+ case AncestorGenerator::Ancestor::kSliceByStack:
+ return context->storage->slice_table().GetColumnCount();
}
return 0;
}
template <typename T>
+Table ExtendTableWithStartId(const T& table, int64_t constraint_value) {
+ // Add a new column that includes the constraint.
+ std::unique_ptr<NullableVector<int64_t>> child_ids(
+ new NullableVector<int64_t>());
+ for (uint32_t i = 0; i < table.row_count(); ++i)
+ child_ids->Append(constraint_value);
+ return table.ExtendWithColumn(
+ "start_id", std::move(child_ids),
+ TypedColumn<uint32_t>::default_flags() | TypedColumn<uint32_t>::kHidden);
+}
+
+template <typename T>
base::Optional<RowMap> BuildAncestorsRowMap(const T& table,
typename T::Id starting_id) {
auto start_row = table.id().IndexOf(starting_id);
@@ -61,24 +75,20 @@
return RowMap(std::move(parent_rows));
}
+// Constraint_value is used to construct the hidden column "start_id"
+// needed by SQL.
+// Starting_id refers to the id that is used to generate the ancestors.
template <typename T>
-std::unique_ptr<Table> BuildAncestorsTable(const T& table,
+std::unique_ptr<Table> BuildAncestorsTable(int64_t constraint_value,
+ 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)));
+ return std::unique_ptr<Table>(new Table(ExtendTableWithStartId(
+ table.Apply(std::move(*ancestors)), constraint_value)));
}
} // namespace
@@ -107,16 +117,38 @@
return c.col_idx == column && c.op == FilterOp::kEq;
});
PERFETTO_DCHECK(it != cs.end());
+ auto start_id = it->value.AsLong();
- auto start_id = static_cast<uint32_t>(it->value.AsLong());
switch (type_) {
case Ancestor::kSlice:
- return BuildAncestorsTable(context_->storage->slice_table(),
- SliceId(start_id));
+ return BuildAncestorsTable(
+ /* constraint_id = */ start_id, context_->storage->slice_table(),
+ /* starting_id = */ SliceId(static_cast<uint32_t>(start_id)));
case Ancestor::kStackProfileCallsite:
return BuildAncestorsTable(
+ /* constraint_id = */ start_id,
context_->storage->stack_profile_callsite_table(),
- CallsiteId(start_id));
+ /* starting_id = */ CallsiteId(static_cast<uint32_t>(start_id)));
+ case Ancestor::kSliceByStack:
+ // Find the all slice ids that have the stack id and find all the
+ // ancestors of the slice ids.
+ const auto& slice_table = context_->storage->slice_table();
+
+ auto result = RowMap();
+ auto slice_ids =
+ slice_table.FilterToRowMap({slice_table.stack_id().eq(start_id)});
+
+ for (auto id_it = slice_ids.IterateRows(); id_it; id_it.Next()) {
+ auto slice_id = slice_table.id()[id_it.row()];
+
+ auto ancestors = GetAncestorSlices(slice_table, slice_id);
+ for (auto row_it = ancestors->IterateRows(); row_it; row_it.Next()) {
+ result.Insert(row_it.row());
+ }
+ }
+
+ return std::unique_ptr<Table>(new Table(ExtendTableWithStartId(
+ slice_table.Apply(std::move(result)), start_id)));
}
return nullptr;
}
@@ -130,6 +162,9 @@
case Ancestor::kStackProfileCallsite:
final_schema = tables::StackProfileCallsiteTable::Schema();
break;
+ case Ancestor::kSliceByStack:
+ final_schema = tables::SliceTable::Schema();
+ break;
}
final_schema.columns.push_back(Table::Schema::Column{
"start_id", SqlValue::Type::kLong, /* is_id = */ false,
@@ -143,6 +178,8 @@
return "ancestor_slice";
case Ancestor::kStackProfileCallsite:
return "experimental_ancestor_stack_profile_callsite";
+ case Ancestor::kSliceByStack:
+ return "ancestor_slice_by_stack";
}
return "ancestor_unknown";
}
diff --git a/src/trace_processor/dynamic/ancestor_generator.h b/src/trace_processor/dynamic/ancestor_generator.h
index bf6324e..2e1f8f0 100644
--- a/src/trace_processor/dynamic/ancestor_generator.h
+++ b/src/trace_processor/dynamic/ancestor_generator.h
@@ -30,11 +30,16 @@
// Implements the following dynamic tables:
// * ancestor_slice
// * experimental_ancestor_stack_profile_callsite
+// * ancestor_slice_by_stack
//
// See docs/analysis/trace-processor for usage.
class AncestorGenerator : public DbSqliteTable::DynamicTableGenerator {
public:
- enum class Ancestor { kSlice = 1, kStackProfileCallsite = 2 };
+ enum class Ancestor {
+ kSlice = 1,
+ kStackProfileCallsite = 2,
+ kSliceByStack = 3
+ };
AncestorGenerator(Ancestor type, TraceProcessorContext* context);
diff --git a/src/trace_processor/dynamic/connected_flow_generator.cc b/src/trace_processor/dynamic/connected_flow_generator.cc
index c8fb57d..6dd0a90 100644
--- a/src/trace_processor/dynamic/connected_flow_generator.cc
+++ b/src/trace_processor/dynamic/connected_flow_generator.cc
@@ -21,7 +21,7 @@
#include <set>
#include "src/trace_processor/dynamic/ancestor_generator.h"
-#include "src/trace_processor/dynamic/descendant_slice_generator.h"
+#include "src/trace_processor/dynamic/descendant_generator.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
#include "src/trace_processor/types/trace_processor_context.h"
@@ -127,7 +127,7 @@
}
if (visit_relatives & VISIT_DESCENDANTS) {
base::Optional<RowMap> descendants =
- DescendantSliceGenerator::GetDescendantSlices(
+ DescendantGenerator::GetDescendantSlices(
context_->storage->slice_table(), slice_id);
GoToRelativesImpl(descendants->IterateRows());
}
diff --git a/src/trace_processor/dynamic/descendant_generator.cc b/src/trace_processor/dynamic/descendant_generator.cc
new file mode 100644
index 0000000..863178a
--- /dev/null
+++ b/src/trace_processor/dynamic/descendant_generator.cc
@@ -0,0 +1,162 @@
+/*
+ * 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/descendant_generator.h"
+
+#include <memory>
+#include <set>
+
+#include "src/trace_processor/types/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+uint32_t GetConstraintColumnIndex(TraceProcessorContext* context) {
+ return context->storage->slice_table().GetColumnCount();
+}
+
+template <typename T>
+Table ExtendTableWithStartId(const T& table, int64_t constraint_value) {
+ // Add a new column that includes the constraint.
+ std::unique_ptr<NullableVector<int64_t>> child_ids(
+ new NullableVector<int64_t>());
+ for (uint32_t i = 0; i < table.row_count(); ++i)
+ child_ids->Append(constraint_value);
+ return table.ExtendWithColumn(
+ "start_id", std::move(child_ids),
+ TypedColumn<uint32_t>::default_flags() | TypedColumn<uint32_t>::kHidden);
+}
+
+base::Optional<RowMap> BuildDescendantsRowMap(const tables::SliceTable& slices,
+ SliceId starting_id) {
+ auto start_row = slices.id().IndexOf(starting_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 slices.FilterToRowMap(
+ {slices.ts().ge(slices.ts()[*start_row]),
+ slices.ts().le(slices.ts()[*start_row] + slices.dur()[*start_row]),
+ slices.track_id().eq(slices.track_id()[*start_row].value),
+ slices.depth().gt(slices.depth()[*start_row])});
+}
+
+std::unique_ptr<Table> BuildDescendantsTable(int64_t constraint_value,
+ const tables::SliceTable& slices,
+ SliceId starting_id) {
+ // Build up all the children row ids.
+ auto descendants = BuildDescendantsRowMap(slices, starting_id);
+ if (!descendants) {
+ return nullptr;
+ }
+ return std::unique_ptr<Table>(new Table(ExtendTableWithStartId(
+ slices.Apply(std::move(*descendants)), constraint_value)));
+}
+} // namespace
+
+DescendantGenerator::DescendantGenerator(Descendant type,
+ TraceProcessorContext* context)
+ : type_(type), context_(context) {}
+
+util::Status DescendantGenerator::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> DescendantGenerator::ComputeTable(
+ const std::vector<Constraint>& cs,
+ const std::vector<Order>&) {
+ const auto& slices = context_->storage->slice_table();
+
+ uint32_t column = GetConstraintColumnIndex(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 = it->value.AsLong();
+
+ switch (type_) {
+ case Descendant::kSlice:
+ return BuildDescendantsTable(start_id, slices,
+ SliceId(static_cast<uint32_t>(start_id)));
+ case Descendant::kSliceByStack:
+ auto result = RowMap();
+ auto slice_ids = slices.FilterToRowMap({slices.stack_id().eq(start_id)});
+
+ for (auto id_it = slice_ids.IterateRows(); id_it; id_it.Next()) {
+ auto slice_id = slices.id()[id_it.row()];
+
+ auto descendants = GetDescendantSlices(slices, slice_id);
+ for (auto row_it = descendants->IterateRows(); row_it; row_it.Next()) {
+ result.Insert(row_it.row());
+ }
+ }
+
+ return std::unique_ptr<Table>(new Table(
+ ExtendTableWithStartId(slices.Apply(std::move(result)), start_id)));
+ }
+ return nullptr;
+}
+
+Table::Schema DescendantGenerator::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 DescendantGenerator::TableName() {
+ switch (type_) {
+ case Descendant::kSlice:
+ return "descendant_slice";
+ case Descendant::kSliceByStack:
+ return "descendant_slice_by_stack";
+ }
+ return "descendant_unknown";
+}
+
+uint32_t DescendantGenerator::EstimateRowCount() {
+ return 1;
+}
+
+// static
+base::Optional<RowMap> DescendantGenerator::GetDescendantSlices(
+ const tables::SliceTable& slices,
+ SliceId slice_id) {
+ return BuildDescendantsRowMap(slices, slice_id);
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/dynamic/descendant_slice_generator.h b/src/trace_processor/dynamic/descendant_generator.h
similarity index 71%
rename from src/trace_processor/dynamic/descendant_slice_generator.h
rename to src/trace_processor/dynamic/descendant_generator.h
index c152f7a..6e87a61 100644
--- a/src/trace_processor/dynamic/descendant_slice_generator.h
+++ b/src/trace_processor/dynamic/descendant_generator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_DESCENDANT_SLICE_GENERATOR_H_
-#define SRC_TRACE_PROCESSOR_DYNAMIC_DESCENDANT_SLICE_GENERATOR_H_
+#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_DESCENDANT_GENERATOR_H_
+#define SRC_TRACE_PROCESSOR_DYNAMIC_DESCENDANT_GENERATOR_H_
#include "src/trace_processor/sqlite/db_sqlite_table.h"
@@ -27,13 +27,16 @@
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 {
+// Implements the following dynamic tables:
+// * descendant_slice
+// * descendant_slice_by_stack
+//
+// See docs/analysis/trace-processor for usage.
+class DescendantGenerator : public DbSqliteTable::DynamicTableGenerator {
public:
- explicit DescendantSliceGenerator(TraceProcessorContext* context);
- ~DescendantSliceGenerator() override;
+ enum class Descendant { kSlice = 1, kSliceByStack = 2 };
+
+ DescendantGenerator(Descendant type, TraceProcessorContext* context);
Table::Schema CreateSchema() override;
std::string TableName() override;
@@ -47,13 +50,14 @@
// ConnectedFlowGenerator to traverse flow indirectly connected flow events.
static base::Optional<RowMap> GetDescendantSlices(
const tables::SliceTable& slices,
- SliceId start_id);
+ SliceId slice_id);
private:
+ Descendant type_;
TraceProcessorContext* context_ = nullptr;
};
} // namespace trace_processor
} // namespace perfetto
-#endif // SRC_TRACE_PROCESSOR_DYNAMIC_DESCENDANT_SLICE_GENERATOR_H_
+#endif // SRC_TRACE_PROCESSOR_DYNAMIC_DESCENDANT_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/experimental_flamegraph_generator.cc b/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
index 90f52e9..960e0d7 100644
--- a/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
+++ b/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
@@ -27,13 +27,42 @@
namespace {
+ExperimentalFlamegraphGenerator::ProfileType extractProfileType(
+ std::string& profile_name) {
+ if (profile_name == "graph") {
+ return ExperimentalFlamegraphGenerator::ProfileType::kGraph;
+ }
+ if (profile_name == "native") {
+ return ExperimentalFlamegraphGenerator::ProfileType::kNative;
+ }
+ if (profile_name == "perf") {
+ return ExperimentalFlamegraphGenerator::ProfileType::kPerf;
+ }
+ PERFETTO_FATAL("Could not recognize profile type: %s.", profile_name.c_str());
+}
+
+bool IsValidTimestampOp(int op) {
+ return op == SQLITE_INDEX_CONSTRAINT_EQ || op == SQLITE_INDEX_CONSTRAINT_GT ||
+ op == SQLITE_INDEX_CONSTRAINT_LE || op == SQLITE_INDEX_CONSTRAINT_LT ||
+ op == SQLITE_INDEX_CONSTRAINT_GE;
+}
+
+bool IsValidFilterOp(FilterOp filterOp) {
+ return filterOp == FilterOp::kEq || filterOp == FilterOp::kGt ||
+ filterOp == FilterOp::kLe || filterOp == FilterOp::kLt ||
+ filterOp == FilterOp::kGe;
+}
+
+// For filtering, this method uses the same constraints as
+// ExperimentalFlamegraphGenerator::ValidateConstraints and should therefore
+// be kept in sync.
ExperimentalFlamegraphGenerator::InputValues GetFlamegraphInputValues(
const std::vector<Constraint>& cs) {
using T = tables::ExperimentalFlamegraphNodesTable;
auto ts_fn = [](const Constraint& c) {
return c.col_idx == static_cast<uint32_t>(T::ColumnIndex::ts) &&
- c.op == FilterOp::kEq;
+ IsValidFilterOp(c.op);
};
auto upid_fn = [](const Constraint& c) {
return c.col_idx == static_cast<uint32_t>(T::ColumnIndex::upid) &&
@@ -55,18 +84,37 @@
// We should always have valid iterators here because BestIndex should only
// allow the constraint set to be chosen when we have an equality constraint
- // on both ts and upid.
+ // on upid and a constraint on ts.
PERFETTO_CHECK(ts_it != cs.end());
PERFETTO_CHECK(upid_it != cs.end());
PERFETTO_CHECK(profile_type_it != cs.end());
- int64_t ts = ts_it->value.AsLong();
- UniquePid upid = static_cast<UniquePid>(upid_it->value.AsLong());
- std::string profile_type = profile_type_it->value.AsString();
+ std::string profile_name(profile_type_it->value.AsString());
+ ExperimentalFlamegraphGenerator::ProfileType profile_type =
+ extractProfileType(profile_name);
+ int64_t ts = -1;
+ std::vector<TimeConstraints> time_constraints = {};
+
+ for (; ts_it != cs.end(); ts_it++) {
+ if (ts_it->col_idx != static_cast<uint32_t>(T::ColumnIndex::ts)) {
+ continue;
+ }
+
+ if (profile_type == ExperimentalFlamegraphGenerator::ProfileType::kPerf) {
+ PERFETTO_CHECK(ts_it->op != FilterOp::kEq);
+ time_constraints.push_back(
+ TimeConstraints{ts_it->op, ts_it->value.AsLong()});
+ } else {
+ PERFETTO_CHECK(ts_it->op == FilterOp::kEq);
+ ts = ts_it->value.AsLong();
+ }
+ }
+
+ auto upid = static_cast<UniquePid>(upid_it->value.AsLong());
std::string focus_str =
focus_str_it != cs.end() ? focus_str_it->value.AsString() : "";
- return ExperimentalFlamegraphGenerator::InputValues{ts, upid, profile_type,
- focus_str};
+ return ExperimentalFlamegraphGenerator::InputValues{
+ profile_type, ts, std::move(time_constraints), upid, focus_str};
}
class Matcher {
@@ -218,6 +266,9 @@
ExperimentalFlamegraphGenerator::~ExperimentalFlamegraphGenerator() = default;
+// For filtering, this method uses the same constraints as
+// ExperimentalFlamegraphGenerator::GetFlamegraphInputValues and should
+// therefore be kept in sync.
util::Status ExperimentalFlamegraphGenerator::ValidateConstraints(
const QueryConstraints& qc) {
using T = tables::ExperimentalFlamegraphNodesTable;
@@ -226,7 +277,7 @@
auto ts_fn = [](const QueryConstraints::Constraint& c) {
return c.column == static_cast<int>(T::ColumnIndex::ts) &&
- c.op == SQLITE_INDEX_CONSTRAINT_EQ;
+ IsValidTimestampOp(c.op);
};
bool has_ts_cs = std::find_if(cs.begin(), cs.end(), ts_fn) != cs.end();
@@ -255,13 +306,15 @@
auto values = GetFlamegraphInputValues(cs);
std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> table;
- if (values.profile_type == "graph") {
+ if (values.profile_type == ProfileType::kGraph) {
auto* tracker = HeapGraphTracker::GetOrCreate(context_);
table = tracker->BuildFlamegraph(values.ts, values.upid);
- }
- if (values.profile_type == "native") {
- table =
- BuildNativeFlamegraph(context_->storage.get(), values.upid, values.ts);
+ } else if (values.profile_type == ProfileType::kNative) {
+ table = BuildNativeHeapProfileFlamegraph(context_->storage.get(),
+ values.upid, values.ts);
+ } else if (values.profile_type == ProfileType::kPerf) {
+ table = BuildNativeCallStackSamplingFlamegraph(
+ context_->storage.get(), values.upid, values.time_constraints);
}
if (!values.focus_str.empty()) {
table =
diff --git a/src/trace_processor/dynamic/experimental_flamegraph_generator.h b/src/trace_processor/dynamic/experimental_flamegraph_generator.h
index 7ca1f51..78afe81 100644
--- a/src/trace_processor/dynamic/experimental_flamegraph_generator.h
+++ b/src/trace_processor/dynamic/experimental_flamegraph_generator.h
@@ -17,6 +17,7 @@
#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_FLAMEGRAPH_GENERATOR_H_
#define SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_FLAMEGRAPH_GENERATOR_H_
+#include "src/trace_processor/importers/proto/flamegraph_construction_algorithms.h"
#include "src/trace_processor/sqlite/db_sqlite_table.h"
#include "src/trace_processor/storage/trace_storage.h"
@@ -29,10 +30,13 @@
class ExperimentalFlamegraphGenerator
: public DbSqliteTable::DynamicTableGenerator {
public:
+ enum class ProfileType { kGraph, kNative, kPerf };
+
struct InputValues {
+ ProfileType profile_type;
int64_t ts;
+ std::vector<TimeConstraints> time_constraints;
UniquePid upid;
- std::string profile_type;
std::string focus_str;
};
diff --git a/src/trace_processor/dynamic/experimental_flat_slice_generator.cc b/src/trace_processor/dynamic/experimental_flat_slice_generator.cc
new file mode 100644
index 0000000..a05cb81
--- /dev/null
+++ b/src/trace_processor/dynamic/experimental_flat_slice_generator.cc
@@ -0,0 +1,265 @@
+/*
+ * 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_flat_slice_generator.h"
+
+#include <memory>
+#include <set>
+
+#include "src/trace_processor/types/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+ExperimentalFlatSliceGenerator::ExperimentalFlatSliceGenerator(
+ TraceProcessorContext* context)
+ : context_(context) {}
+
+util::Status ExperimentalFlatSliceGenerator::ValidateConstraints(
+ const QueryConstraints& qc) {
+ using CI = tables::ExperimentalFlatSliceTable::ColumnIndex;
+ bool has_start_bound = false;
+ bool has_end_bound = false;
+ for (const auto& c : qc.constraints()) {
+ has_start_bound |= c.column == static_cast<int>(CI::start_bound) &&
+ c.op == SQLITE_INDEX_CONSTRAINT_EQ;
+ has_end_bound |= c.column == static_cast<int>(CI::end_bound) &&
+ c.op == SQLITE_INDEX_CONSTRAINT_EQ;
+ }
+ return has_start_bound && has_end_bound
+ ? util::OkStatus()
+ : util::ErrStatus("Failed to find required constraints");
+}
+
+std::unique_ptr<Table> ExperimentalFlatSliceGenerator::ComputeTable(
+ const std::vector<Constraint>& cs,
+ const std::vector<Order>&) {
+ using CI = tables::ExperimentalFlatSliceTable::ColumnIndex;
+ auto start_it = std::find_if(cs.begin(), cs.end(), [](const Constraint& c) {
+ return c.col_idx == static_cast<uint32_t>(CI::start_bound) &&
+ c.op == FilterOp::kEq;
+ });
+ auto end_it = std::find_if(cs.begin(), cs.end(), [](const Constraint& c) {
+ return c.col_idx == static_cast<uint32_t>(CI::end_bound) &&
+ c.op == FilterOp::kEq;
+ });
+ int64_t start_bound = start_it->value.AsLong();
+ int64_t end_bound = end_it->value.AsLong();
+ return ComputeFlatSliceTable(context_->storage->slice_table(),
+ context_->storage->mutable_string_pool(),
+ start_bound, end_bound);
+}
+
+std::unique_ptr<tables::ExperimentalFlatSliceTable>
+ExperimentalFlatSliceGenerator::ComputeFlatSliceTable(
+ const tables::SliceTable& slice,
+ StringPool* pool,
+ int64_t start_bound,
+ int64_t end_bound) {
+ std::unique_ptr<tables::ExperimentalFlatSliceTable> out(
+ new tables::ExperimentalFlatSliceTable(pool, nullptr));
+
+ auto insert_slice = [&](uint32_t i, int64_t ts,
+ tables::TrackTable::Id track_id) {
+ tables::ExperimentalFlatSliceTable::Row row;
+ row.ts = ts;
+ row.dur = -1;
+ row.track_id = track_id;
+ row.category = slice.category()[i];
+ row.name = slice.name()[i];
+ row.arg_set_id = slice.arg_set_id()[i];
+ row.source_id = slice.id()[i];
+ row.start_bound = start_bound;
+ row.end_bound = end_bound;
+ return out->Insert(row).row;
+ };
+ auto insert_sentinel = [&](int64_t ts, TrackId track_id) {
+ tables::ExperimentalFlatSliceTable::Row row;
+ row.ts = ts;
+ row.dur = -1;
+ row.track_id = track_id;
+ row.category = kNullStringId;
+ row.name = kNullStringId;
+ row.arg_set_id = kInvalidArgSetId;
+ row.source_id = base::nullopt;
+ row.start_bound = start_bound;
+ row.end_bound = end_bound;
+ return out->Insert(row).row;
+ };
+
+ auto terminate_slice = [&](uint32_t out_row, int64_t end_ts) {
+ PERFETTO_DCHECK(out->dur()[out_row] == -1);
+ int64_t out_ts = out->ts()[out_row];
+ out->mutable_dur()->Set(out_row, end_ts - out_ts);
+ };
+
+ struct ActiveSlice {
+ base::Optional<uint32_t> source_row;
+ uint32_t out_row = std::numeric_limits<uint32_t>::max();
+
+ bool is_sentinel() const { return !source_row; }
+ };
+ struct Track {
+ std::vector<uint32_t> parents;
+ ActiveSlice active;
+ bool initialized = false;
+ };
+ std::unordered_map<TrackId, Track> tracks;
+
+ auto maybe_terminate_active_slice = [&](const Track& t, int64_t fin_ts) {
+ int64_t ts = slice.ts()[t.active.source_row.value()];
+ int64_t dur = slice.dur()[t.active.source_row.value()];
+ if (dur == -1 || ts + dur > fin_ts)
+ return false;
+
+ terminate_slice(t.active.out_row, ts + dur);
+ return true;
+ };
+
+ // Post-condition: |tracks[track_id].active| will always point to
+ // a slice which finishes after |fin_ts| and has a |dur| == -1 in
+ // |out|.
+ auto output_slices_before = [&](TrackId track_id, int64_t fin_ts) {
+ auto& t = tracks[track_id];
+
+ // A sentinel slice cannot have parents.
+ PERFETTO_DCHECK(!t.active.is_sentinel() || t.parents.empty());
+
+ // If we have a sentinel slice active, we have nothing to output.
+ if (t.active.is_sentinel())
+ return;
+
+ // Try and terminate the current slice (if it ends before |fin_ts|)
+ // If we cannot terminate it, then we leave it as pending for the caller
+ // to terminate.
+ if (!maybe_terminate_active_slice(t, fin_ts))
+ return;
+
+ // Next, add any parents as appropriate.
+ for (int64_t i = static_cast<int64_t>(t.parents.size()) - 1; i >= 0; --i) {
+ uint32_t source_row = t.parents[static_cast<size_t>(i)];
+ t.parents.pop_back();
+
+ int64_t active_ts = out->ts()[t.active.out_row];
+ int64_t active_dur = out->dur()[t.active.out_row];
+ PERFETTO_DCHECK(active_dur != -1);
+
+ t.active.source_row = source_row;
+ t.active.out_row =
+ insert_slice(source_row, active_ts + active_dur, track_id);
+
+ if (!maybe_terminate_active_slice(t, fin_ts))
+ break;
+ }
+
+ if (!t.parents.empty())
+ return;
+
+ // If the active slice is a sentinel, the check at the top of this function
+ // should have caught it; all code only adds slices from source.
+ PERFETTO_DCHECK(!t.active.is_sentinel());
+
+ int64_t ts = out->ts()[t.active.out_row];
+ int64_t dur = out->dur()[t.active.out_row];
+
+ // If the active slice is unfinshed, we return that for the caller to
+ // terminate.
+ if (dur == -1)
+ return;
+
+ // Otherwise, Add a sentinel slice after the end of the active slice.
+ t.active.source_row = base::nullopt;
+ t.active.out_row = insert_sentinel(ts + dur, track_id);
+ };
+
+ for (uint32_t i = 0; i < slice.row_count(); ++i) {
+ // TODO(lalitm): this can be optimized using a O(logn) lower bound/filter.
+ // Not adding for now as a premature optimization but may be needed down the
+ // line.
+ int64_t ts = slice.ts()[i];
+ if (ts < start_bound)
+ continue;
+
+ if (ts >= end_bound)
+ break;
+
+ // Ignore instants as they don't factor into flat slice at all.
+ if (slice.dur()[i] == 0)
+ continue;
+
+ TrackId track_id = slice.track_id()[i];
+ Track& track = tracks[track_id];
+
+ // Initalize the track (if needed) by adding a sentinel slice starting at
+ // start_bound.
+ bool is_root = slice.depth()[i] == 0;
+ if (!track.initialized) {
+ // If we are unintialized and our start box picks up slices mid way
+ // through startup, wait until we reach a root slice.
+ if (!is_root)
+ continue;
+
+ track.active.out_row = insert_sentinel(start_bound, track_id);
+ track.initialized = true;
+ }
+ output_slices_before(track_id, ts);
+ terminate_slice(track.active.out_row, ts);
+
+ // We should have sentinel slices iff the slice is a root.
+ PERFETTO_DCHECK(track.active.is_sentinel() == is_root);
+
+ // If our current slice has a parent, that must be the current active slice.
+ if (!is_root) {
+ track.parents.push_back(*track.active.source_row);
+ }
+
+ // The depth of our slice should also match the depth of the parent stack
+ // (after adding the previous slice).
+ PERFETTO_DCHECK(track.parents.size() == slice.depth()[i]);
+
+ track.active.source_row = i;
+ track.active.out_row = insert_slice(i, ts, track_id);
+ }
+
+ for (const auto& track : tracks) {
+ // If the track is not initialized, don't add anything.
+ if (!track.second.initialized)
+ continue;
+
+ // First, terminate any hanging slices.
+ output_slices_before(track.first, end_bound);
+
+ // Second, force terminate the final slice to the end bound.
+ terminate_slice(track.second.active.out_row, end_bound);
+ }
+
+ return out;
+}
+
+Table::Schema ExperimentalFlatSliceGenerator::CreateSchema() {
+ return tables::ExperimentalFlatSliceTable::Schema();
+}
+
+std::string ExperimentalFlatSliceGenerator::TableName() {
+ return "experimental_flat_slice";
+}
+
+uint32_t ExperimentalFlatSliceGenerator::EstimateRowCount() {
+ return context_->storage->slice_table().row_count();
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/dynamic/experimental_flat_slice_generator.h b/src/trace_processor/dynamic/experimental_flat_slice_generator.h
new file mode 100644
index 0000000..b0838c4
--- /dev/null
+++ b/src/trace_processor/dynamic/experimental_flat_slice_generator.h
@@ -0,0 +1,81 @@
+/*
+ * 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_FLAT_SLICE_GENERATOR_H_
+#define SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_FLAT_SLICE_GENERATOR_H_
+
+#include "perfetto/ext/base/optional.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 generator for "flat slice" table.
+//
+// The concept of a "flat slice" is to take the data in the slice table and
+// remove all notion of nesting; we do this by, at any point in time, taking the
+// most specific active slice (i.e. the slice at the bottom of the stack) and
+// representing that as the *only* slice that was running during that period.
+//
+// This concept becomes very useful when you try and linearise a trace and
+// compare it with other traces spanning the same user action; "self time" (i.e.
+// time spent in a slice but *not* any children) is easily computed and span
+// joins with thread state become possible without limiting to only depth zero
+// slices.
+//
+// This table also adds "gap slices" which fill in the gap between top level
+// slices with a sentinal values so that comparision of the gap between slices
+// is also possible.
+//
+// As input, this generator takes a start and end timestamp between
+// which slices should be picked; we do this rather than just using the trace
+// bounds so that the "gap slices" start and end at the appropriate place.
+//
+// Note that for the start bound we will *not* pick any slice which started
+// before the bound even if it finished after. This is dissimilar to span join
+// (which picks all slices with ts + dur >= bound) and is more akin to doing
+// a simple ts >= bound. However, slices *will* be truncated at the end
+// if they would spill past the provided end bound.
+class ExperimentalFlatSliceGenerator
+ : public DbSqliteTable::DynamicTableGenerator {
+ public:
+ ExperimentalFlatSliceGenerator(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;
+
+ // Visibile for testing.
+ static std::unique_ptr<tables::ExperimentalFlatSliceTable>
+ ComputeFlatSliceTable(const tables::SliceTable&,
+ StringPool*,
+ int64_t start_bound,
+ int64_t end_bound);
+
+ private:
+ TraceProcessorContext* context_ = nullptr;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_FLAT_SLICE_GENERATOR_H_
diff --git a/src/trace_processor/dynamic/experimental_flat_slice_generator_unittest.cc b/src/trace_processor/dynamic/experimental_flat_slice_generator_unittest.cc
new file mode 100644
index 0000000..fd1bac7
--- /dev/null
+++ b/src/trace_processor/dynamic/experimental_flat_slice_generator_unittest.cc
@@ -0,0 +1,202 @@
+/*
+ * 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_flat_slice_generator.h"
+
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+class TableInseter {
+ public:
+ void Insert(int64_t ts, int64_t dur, uint32_t depth, TrackId track_id) {
+ tables::SliceTable::Row row;
+ row.ts = ts;
+ row.dur = dur;
+ row.depth = depth;
+ row.track_id = track_id;
+ rows_.emplace_back(std::move(row));
+ }
+
+ void Populate(tables::SliceTable& table) {
+ using R = tables::SliceTable::Row;
+ std::sort(rows_.begin(), rows_.end(),
+ [](const R& a, const R& b) { return a.ts < b.ts; });
+ for (const auto& row : rows_) {
+ table.Insert(row);
+ }
+ rows_.clear();
+ }
+
+ private:
+ std::vector<tables::SliceTable::Row> rows_;
+};
+
+class TableAsserter {
+ public:
+ TableAsserter(Table table) : table_(std::move(table)) {}
+
+ void NextSlice(int64_t ts, int64_t dur) {
+ ++idx_;
+ ASSERT_LT(idx_, table_.row_count());
+ ASSERT_EQ(table_.GetTypedColumnByName<int64_t>("ts")[idx_], ts)
+ << "where idx_ = " << idx_;
+ ASSERT_EQ(table_.GetTypedColumnByName<int64_t>("dur")[idx_], dur)
+ << "where idx_ = " << idx_;
+ }
+
+ bool HasMoreSlices() { return idx_ + 1 < table_.row_count(); }
+
+ private:
+ Table table_;
+ uint32_t idx_ = std::numeric_limits<uint32_t>::max();
+};
+
+TEST(ExperimentalFlatSliceGenerator, Smoke) {
+ StringPool pool;
+ TableInseter inserter;
+ tables::SliceTable table(&pool, nullptr);
+
+ // A simple stack on track 1.
+ inserter.Insert(100, 10, 0, TrackId{1});
+ inserter.Insert(104, 6, 1, TrackId{1});
+ inserter.Insert(107, 1, 2, TrackId{1});
+
+ // Back to back slices with a gap on track 2.
+ inserter.Insert(200, 10, 0, TrackId{2});
+ inserter.Insert(210, 10, 0, TrackId{2});
+ inserter.Insert(230, 10, 0, TrackId{2});
+
+ // Deep nesting on track 3.
+ inserter.Insert(300, 100, 0, TrackId{3});
+ inserter.Insert(301, 98, 1, TrackId{3});
+ inserter.Insert(302, 96, 2, TrackId{3});
+ inserter.Insert(303, 94, 3, TrackId{3});
+ inserter.Insert(304, 92, 4, TrackId{3});
+ inserter.Insert(305, 90, 5, TrackId{3});
+
+ // Populate the table.
+ inserter.Populate(table);
+
+ auto out = ExperimentalFlatSliceGenerator::ComputeFlatSliceTable(table, &pool,
+ 0, 400);
+ auto sorted = out->Sort({out->track_id().ascending(), out->ts().ascending()});
+
+ TableAsserter asserter(std::move(sorted));
+
+ // Track 1's slices.
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 100));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(100, 4));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(104, 3));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(107, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(108, 2));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(110, 0));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(110, 290));
+
+ // Track 2's slices.
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 200));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 10));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 0));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 10));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(220, 10));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(230, 10));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(240, 160));
+
+ // Track 3's slices.
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 300));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(300, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(301, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(302, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(303, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(304, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(305, 90));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(395, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(396, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(397, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(398, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(399, 1));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(400, 0));
+
+ ASSERT_FALSE(asserter.HasMoreSlices());
+}
+
+TEST(ExperimentalFlatSliceGenerator, Bounds) {
+ StringPool pool;
+ TableInseter inserter;
+ tables::SliceTable table(&pool, nullptr);
+
+ /// Our timebounds is between 200 and 300.
+ int64_t start = 200;
+ int64_t end = 300;
+
+ // Track 1 has all events inside bounds.
+ inserter.Insert(200, 10, 0, TrackId{1});
+ inserter.Insert(210, 10, 0, TrackId{1});
+ inserter.Insert(230, 10, 0, TrackId{1});
+
+ // Track 2 has a two stacks, first partially inside at start, second partially
+ // inside at end.
+ // First stack.
+ inserter.Insert(190, 20, 0, TrackId{2});
+ inserter.Insert(200, 9, 1, TrackId{2});
+ inserter.Insert(201, 1, 2, TrackId{2});
+
+ // Second stack.
+ inserter.Insert(290, 20, 0, TrackId{2});
+ inserter.Insert(299, 2, 1, TrackId{2});
+ inserter.Insert(300, 1, 2, TrackId{2});
+
+ // Track 3 has two stacks but *only* outside bounds.
+ inserter.Insert(190, 9, 0, TrackId{3});
+ inserter.Insert(195, 2, 1, TrackId{3});
+
+ inserter.Insert(300, 9, 0, TrackId{3});
+ inserter.Insert(301, 2, 1, TrackId{3});
+
+ // Track 4 has one stack which is partially inside at start.
+ inserter.Insert(190, 20, 0, TrackId{4});
+ inserter.Insert(201, 2, 1, TrackId{4});
+
+ // Populate the table.
+ inserter.Populate(table);
+
+ auto out = ExperimentalFlatSliceGenerator::ComputeFlatSliceTable(table, &pool,
+ start, end);
+ auto sorted = out->Sort({out->track_id().ascending(), out->ts().ascending()});
+
+ TableAsserter asserter(std::move(sorted));
+
+ // Track 1's slices.
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 0));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 10));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 0));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 10));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(220, 10));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(230, 10));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(240, 60));
+
+ // Track 2's slices.
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 90));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(290, 9));
+ ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(299, 1));
+
+ ASSERT_FALSE(asserter.HasMoreSlices());
+}
+
+} // namespace
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/dynamic/experimental_slice_layout_generator.cc b/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
index 0c864a1..5d0f2db 100644
--- a/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
+++ b/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
@@ -235,7 +235,7 @@
{
auto it = still_open.begin();
while (it != still_open.end()) {
- if ((*it)->end < start) {
+ if ((*it)->end <= start) {
it = still_open.erase(it);
} else {
++it;
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index fe73813..01f6617 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -17,11 +17,11 @@
#include "perfetto/ext/trace_processor/export_json.h"
#include "src/trace_processor/export_json.h"
-#include <inttypes.h>
#include <stdio.h>
#include <sstream>
#include <algorithm>
+#include <cinttypes>
#include <cmath>
#include <cstring>
#include <deque>
@@ -85,8 +85,11 @@
const char kLegacyEventIdScopeKey[] = "id_scope";
const char kStrippedArgument[] = "__stripped__";
-const char* GetNonNullString(const TraceStorage* storage, StringId id) {
- return id == kNullStringId ? "" : storage->GetString(id).c_str();
+const char* GetNonNullString(const TraceStorage* storage,
+ base::Optional<StringId> id) {
+ return id == base::nullopt || *id == kNullStringId
+ ? ""
+ : storage->GetString(*id).c_str();
}
class JsonExporter {
@@ -1111,8 +1114,10 @@
} 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()];
+ base::Optional<StringId> cat_id =
+ slice_table.category()[opt_slice_out_idx.value()];
+ base::Optional<StringId> name_id =
+ slice_table.name()[opt_slice_out_idx.value()];
cat = GetNonNullString(storage_, cat_id);
name = GetNonNullString(storage_, name_id);
}
@@ -1929,4 +1934,3 @@
} // namespace json
} // namespace trace_processor
} // namespace perfetto
-
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index 9dadb44..08c4fa2 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -827,7 +827,8 @@
TEST_F(ExportJsonTest, DuplicatePidAndTid) {
UniqueTid upid1 = context_.process_tracker->StartNewProcess(
- base::nullopt, base::nullopt, 1, kNullStringId);
+ base::nullopt, base::nullopt, 1, kNullStringId,
+ ThreadNamePriority::kTrackDescriptor);
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);
@@ -835,7 +836,8 @@
ASSERT_EQ(utid1c, context_.process_tracker->UpdateThread(2, 1));
UniqueTid upid2 = context_.process_tracker->StartNewProcess(
- base::nullopt, base::nullopt, 1, kNullStringId);
+ base::nullopt, base::nullopt, 1, kNullStringId,
+ ThreadNamePriority::kTrackDescriptor);
UniqueTid utid2a = context_.process_tracker->UpdateThread(1, 1);
UniqueTid utid2b = context_.process_tracker->UpdateThread(2, 1);
diff --git a/src/trace_processor/forwarding_trace_parser.cc b/src/trace_processor/forwarding_trace_parser.cc
index 4ba663e..dc2cf54 100644
--- a/src/trace_processor/forwarding_trace_parser.cc
+++ b/src/trace_processor/forwarding_trace_parser.cc
@@ -40,6 +40,17 @@
return str;
}
+TraceSorter::SortingMode ConvertSortingMode(SortingMode sorting_mode) {
+ switch (sorting_mode) {
+ case SortingMode::kDefaultHeuristics:
+ case SortingMode::kForceFlushPeriodWindowedSort:
+ return TraceSorter::SortingMode::kDefault;
+ case SortingMode::kForceFullSort:
+ return TraceSorter::SortingMode::kFullSort;
+ }
+ PERFETTO_FATAL("For GCC");
+}
+
// Fuchsia traces have a magic number as documented here:
// https://fuchsia.googlesource.com/fuchsia/+/HEAD/docs/development/tracing/trace-format/README.md#magic-number-record-trace-info-type-0
constexpr uint64_t kFuchsiaMagicNumber = 0x0016547846040010;
@@ -55,7 +66,6 @@
size_t size) {
// If this is the first Parse() call, guess the trace type and create the
// appropriate parser.
- static const int64_t kMaxWindowSize = std::numeric_limits<int64_t>::max();
if (!reader_) {
TraceType trace_type;
{
@@ -70,8 +80,9 @@
reader_ = std::move(context_->json_trace_tokenizer);
// JSON traces have no guarantees about the order of events in them.
- context_->sorter.reset(new TraceSorter(
- std::move(context_->json_trace_parser), kMaxWindowSize));
+ context_->sorter.reset(
+ new TraceSorter(context_, std::move(context_->json_trace_parser),
+ TraceSorter::SortingMode::kFullSort));
} else {
return util::ErrStatus("JSON support is disabled");
}
@@ -79,12 +90,12 @@
}
case kProtoTraceType: {
PERFETTO_DLOG("Proto trace detected");
- // This will be reduced once we read the trace config and we see flush
- // period being set.
+ auto sorting_mode = ConvertSortingMode(context_->config.sorting_mode);
reader_.reset(new ProtoTraceReader(context_));
context_->sorter.reset(new TraceSorter(
+ context_,
std::unique_ptr<TraceParser>(new ProtoTraceParser(context_)),
- kMaxWindowSize));
+ sorting_mode));
context_->process_tracker->SetPidZeroIgnoredForIdleProcess();
break;
}
@@ -101,7 +112,8 @@
// Fuschia traces can have massively out of order events.
context_->sorter.reset(new TraceSorter(
- std::move(context_->fuchsia_trace_parser), kMaxWindowSize));
+ context_, std::move(context_->fuchsia_trace_parser),
+ TraceSorter::SortingMode::kFullSort));
} else {
return util::ErrStatus("Fuchsia support is disabled");
}
@@ -147,7 +159,7 @@
if (size == 0)
return kUnknownTraceType;
std::string start(reinterpret_cast<const char*>(data),
- std::min<size_t>(size, 20));
+ std::min<size_t>(size, 32));
if (size >= 8) {
uint64_t first_word;
memcpy(&first_word, data, sizeof(first_word));
@@ -155,9 +167,9 @@
return kFuchsiaTraceType;
}
std::string start_minus_white_space = RemoveWhitespace(start);
- if (base::StartsWith(start_minus_white_space, "{"))
+ if (base::StartsWith(start_minus_white_space, "{\""))
return kJsonTraceType;
- if (base::StartsWith(start_minus_white_space, "[{"))
+ if (base::StartsWith(start_minus_white_space, "[{\""))
return kJsonTraceType;
// Systrace with header but no leading HTML.
diff --git a/src/trace_processor/forwarding_trace_parser_unittest.cc b/src/trace_processor/forwarding_trace_parser_unittest.cc
index 048ab14..059caa0 100644
--- a/src/trace_processor/forwarding_trace_parser_unittest.cc
+++ b/src/trace_processor/forwarding_trace_parser_unittest.cc
@@ -44,7 +44,7 @@
// Some Android build traces do not contain the wrapper. See b/118826940
TEST(TraceProcessorImplTest, GuessTraceType_JsonMissingTraceEvents) {
- const uint8_t prefix[] = "[{";
+ const uint8_t prefix[] = "[{\"";
EXPECT_EQ(kJsonTraceType, GuessTraceType(prefix, sizeof(prefix)));
}
diff --git a/src/trace_processor/importers/common/clock_tracker.cc b/src/trace_processor/importers/common/clock_tracker.cc
index 75518a2..61956c2 100644
--- a/src/trace_processor/importers/common/clock_tracker.cc
+++ b/src/trace_processor/importers/common/clock_tracker.cc
@@ -16,10 +16,9 @@
#include "src/trace_processor/importers/common/clock_tracker.h"
-#include <inttypes.h>
-
#include <algorithm>
#include <atomic>
+#include <cinttypes>
#include <queue>
#include "perfetto/base/logging.h"
diff --git a/src/trace_processor/importers/common/clock_tracker.h b/src/trace_processor/importers/common/clock_tracker.h
index 16b9d79..35b316e 100644
--- a/src/trace_processor/importers/common/clock_tracker.h
+++ b/src/trace_processor/importers/common/clock_tracker.h
@@ -17,10 +17,10 @@
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CLOCK_TRACKER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CLOCK_TRACKER_H_
-#include <inttypes.h>
#include <stdint.h>
#include <array>
+#include <cinttypes>
#include <map>
#include <random>
#include <set>
diff --git a/src/trace_processor/importers/common/process_tracker.cc b/src/trace_processor/importers/common/process_tracker.cc
index 173d47d..0981063 100644
--- a/src/trace_processor/importers/common/process_tracker.cc
+++ b/src/trace_processor/importers/common/process_tracker.cc
@@ -17,10 +17,9 @@
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/storage/stats.h"
+#include <cinttypes>
#include <utility>
-#include <inttypes.h>
-
namespace perfetto {
namespace trace_processor {
@@ -62,7 +61,19 @@
auto* thread_table = context_->storage->mutable_thread_table();
auto* process_table = context_->storage->mutable_process_table();
- UniqueTid utid = GetOrCreateThread(tid);
+ // Don't bother creating a new thread if we're just going to
+ // end it straight away.
+ //
+ // This is useful in situations where we get a sched_process_free event for a
+ // worker thread in a process *after* the main thread finishes - in that case
+ // we would have already ended the process and we don't want to
+ // create a new thread here (see b/193520421 for an example of a trace
+ // where this happens in practice).
+ base::Optional<UniqueTid> opt_utid = GetThreadOrNull(tid);
+ if (!opt_utid)
+ return;
+
+ UniqueTid utid = *opt_utid;
thread_table->mutable_end_ts()->Set(utid, timestamp);
// Remove the thread from the list of threads being tracked as any event after
@@ -71,13 +82,14 @@
vector.erase(std::remove(vector.begin(), vector.end(), utid));
auto opt_upid = thread_table->upid()[utid];
- if (opt_upid.has_value()) {
- // If the process pid and thread tid are equal, then this is the main thread
- // of the process.
- if (process_table->pid()[*opt_upid] == thread_table->tid()[utid]) {
- process_table->mutable_end_ts()->Set(*opt_upid, timestamp);
- }
- }
+ if (!opt_upid.has_value() || process_table->pid()[*opt_upid] != tid)
+ return;
+
+ // If the process pid and thread tid are equal then, as is the main thread
+ // of the process, we should also finish the process itself.
+ PERFETTO_DCHECK(thread_table->is_main_thread()[utid].value());
+ process_table->mutable_end_ts()->Set(*opt_upid, timestamp);
+ pids_.erase(tid);
}
base::Optional<UniqueTid> ProcessTracker::GetThreadOrNull(uint32_t tid) {
@@ -211,7 +223,8 @@
UniquePid ProcessTracker::StartNewProcess(base::Optional<int64_t> timestamp,
base::Optional<uint32_t> parent_tid,
uint32_t pid,
- StringId main_thread_name) {
+ StringId main_thread_name,
+ ThreadNamePriority priority) {
pids_.erase(pid);
// TODO(eseckler): Consider erasing all old entries in |tids_| that match the
// |pid| (those would be for an older process with the same pid). Right now,
@@ -220,7 +233,8 @@
// 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);
+ UniqueTid utid = StartNewThread(timestamp, /*tid=*/pid);
+ UpdateThreadNameByUtid(utid, main_thread_name, priority);
// Note that we erased the pid above so this should always return a new
// process.
@@ -253,20 +267,18 @@
base::Optional<uint32_t> ppid,
base::StringView name,
base::StringView cmdline) {
- auto proc_name_id = context_->storage->InternString(name);
-
base::Optional<UniquePid> pupid;
if (ppid.has_value()) {
pupid = GetOrCreateProcess(ppid.value());
}
UniquePid upid = GetOrCreateProcess(pid);
-
auto* process_table = context_->storage->mutable_process_table();
+
+ StringId proc_name_id = context_->storage->InternString(name);
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);
@@ -296,38 +308,41 @@
process_table->mutable_start_ts()->Set(upid, start_ts_nanoseconds);
}
-void ProcessTracker::UpdateProcessNameFromThreadName(uint32_t tid,
- StringId thread_name) {
+void ProcessTracker::UpdateThreadNameAndMaybeProcessName(
+ uint32_t tid,
+ StringId thread_name,
+ ThreadNamePriority priority) {
auto* thread_table = context_->storage->mutable_thread_table();
auto* process_table = context_->storage->mutable_process_table();
- auto utid = GetOrCreateThread(tid);
- auto opt_upid = thread_table->upid()[utid];
- if (opt_upid.has_value()) {
- if (process_table->pid()[*opt_upid] == tid) {
- process_table->mutable_name()->Set(*opt_upid, thread_name);
- }
+ UniqueTid utid = UpdateThreadName(tid, thread_name, priority);
+ base::Optional<UniquePid> opt_upid = thread_table->upid()[utid];
+ if (opt_upid.has_value() && process_table->pid()[*opt_upid] == tid) {
+ PERFETTO_DCHECK(thread_table->is_main_thread()[utid]);
+ process_table->mutable_name()->Set(*opt_upid, thread_name);
}
}
UniquePid ProcessTracker::GetOrCreateProcess(uint32_t pid) {
- UniquePid upid;
+ auto* process_table = context_->storage->mutable_process_table();
auto it = pids_.find(pid);
if (it != pids_.end()) {
- upid = it->second;
- } else {
- tables::ProcessTable::Row row;
- row.pid = pid;
- upid = context_->storage->mutable_process_table()->Insert(row).row;
-
- pids_.emplace(pid, upid);
-
- // Create an entry for the main thread.
- // We cannot call StartNewThread() here, because threads for this process
- // (including the main thread) might have been seen already prior to this
- // call. This call usually comes from the ProcessTree dump which is delayed.
- UpdateThread(/*tid=*/pid, pid);
+ // Ensure that the process has not ended.
+ PERFETTO_DCHECK(!process_table->end_ts()[it->second].has_value());
+ return it->second;
}
+
+ tables::ProcessTable::Row row;
+ row.pid = pid;
+
+ UniquePid upid = process_table->Insert(row).row;
+ pids_.emplace(pid, upid);
+
+ // Create an entry for the main thread.
+ // We cannot call StartNewThread() here, because threads for this process
+ // (including the main thread) might have been seen already prior to this
+ // call. This call usually comes from the ProcessTree dump which is delayed.
+ UpdateThread(/*tid=*/pid, pid);
return upid;
}
diff --git a/src/trace_processor/importers/common/process_tracker.h b/src/trace_processor/importers/common/process_tracker.h
index 3c46c38..1a062cf 100644
--- a/src/trace_processor/importers/common/process_tracker.h
+++ b/src/trace_processor/importers/common/process_tracker.h
@@ -102,7 +102,8 @@
UniquePid StartNewProcess(base::Optional<int64_t> timestamp,
base::Optional<uint32_t> parent_tid,
uint32_t pid,
- StringId main_thread_name);
+ StringId main_thread_name,
+ ThreadNamePriority priority);
// Called when a process is seen in a process tree. Retrieves the UniquePid
// for that pid or assigns a new one.
@@ -123,9 +124,11 @@
// 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);
+ // Called on a task rename event to set the thread name and possibly process
+ // name (if the tid provided is the main thread of the process).
+ void UpdateThreadNameAndMaybeProcessName(uint32_t tid,
+ StringId thread_name,
+ ThreadNamePriority priority);
// Called when a process is seen in a process tree. Retrieves the UniquePid
// for that pid or assigns a new one.
diff --git a/src/trace_processor/importers/common/process_tracker_unittest.cc b/src/trace_processor/importers/common/process_tracker_unittest.cc
index 3b1f9dd..7ed1bd4 100644
--- a/src/trace_processor/importers/common/process_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/process_tracker_unittest.cc
@@ -57,8 +57,8 @@
}
TEST_F(ProcessTrackerTest, StartNewProcess) {
- auto upid =
- context.process_tracker->StartNewProcess(1000, 0u, 123, kNullStringId);
+ auto upid = context.process_tracker->StartNewProcess(
+ 1000, 0u, 123, kNullStringId, ThreadNamePriority::kFtrace);
ASSERT_EQ(context.process_tracker->GetOrCreateProcess(123), upid);
ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
}
@@ -108,11 +108,13 @@
TEST_F(ProcessTrackerTest, PidReuseWithoutStartAndEndThread) {
UniquePid p1 = context.process_tracker->StartNewProcess(
- base::nullopt, base::nullopt, /*pid=*/1, kNullStringId);
+ base::nullopt, base::nullopt, /*pid=*/1, kNullStringId,
+ ThreadNamePriority::kFtrace);
UniqueTid t1 = context.process_tracker->UpdateThread(/*tid=*/2, /*pid=*/1);
UniquePid p2 = context.process_tracker->StartNewProcess(
- base::nullopt, base::nullopt, /*pid=*/1, kNullStringId);
+ base::nullopt, base::nullopt, /*pid=*/1, kNullStringId,
+ ThreadNamePriority::kFtrace);
UniqueTid t2 = context.process_tracker->UpdateThread(/*tid=*/2, /*pid=*/1);
ASSERT_NE(p1, p2);
@@ -156,7 +158,8 @@
TEST_F(ProcessTrackerTest, SetStartTsIfUnset) {
auto upid = context.process_tracker->StartNewProcess(
- /*timestamp=*/base::nullopt, 0u, 123, kNullStringId);
+ /*timestamp=*/base::nullopt, 0u, 123, kNullStringId,
+ ThreadNamePriority::kFtrace);
context.process_tracker->SetStartTsIfUnset(upid, 1000);
ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
@@ -164,6 +167,40 @@
ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
}
+TEST_F(ProcessTrackerTest, PidReuseAfterExplicitEnd) {
+ UniquePid upid = context.process_tracker->GetOrCreateProcess(123);
+ context.process_tracker->EndThread(100, 123);
+
+ UniquePid reuse = context.process_tracker->GetOrCreateProcess(123);
+ ASSERT_NE(upid, reuse);
+}
+
+TEST_F(ProcessTrackerTest, TidReuseAfterExplicitEnd) {
+ UniqueTid utid = context.process_tracker->UpdateThread(123, 123);
+ context.process_tracker->EndThread(100, 123);
+
+ UniqueTid reuse = context.process_tracker->UpdateThread(123, 123);
+ ASSERT_NE(utid, reuse);
+
+ UniqueTid reuse_again = context.process_tracker->UpdateThread(123, 123);
+ ASSERT_EQ(reuse, reuse_again);
+}
+
+TEST_F(ProcessTrackerTest, EndThreadAfterProcessEnd) {
+ context.process_tracker->StartNewProcess(
+ 100, base::nullopt, 123, kNullStringId, ThreadNamePriority::kFtrace);
+ context.process_tracker->UpdateThread(124, 123);
+
+ context.process_tracker->EndThread(200, 123);
+ context.process_tracker->EndThread(201, 124);
+
+ // We expect two processes: the idle process and 123.
+ ASSERT_EQ(context.storage->process_table().row_count(), 2u);
+
+ // We expect three theads: the idle thread, 123 and 124.
+ ASSERT_EQ(context.storage->thread_table().row_count(), 3u);
+}
+
} // 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..dbb76a2 100644
--- a/src/trace_processor/importers/common/slice_tracker.cc
+++ b/src/trace_processor/importers/common/slice_tracker.cc
@@ -252,13 +252,16 @@
uint32_t slice_idx = stack[static_cast<size_t>(i)].row;
if (slices->dur()[slice_idx] != kPendingDuration)
continue;
- const StringId& other_category = slices->category()[slice_idx];
- if (!category.is_null() &&
- (other_category.is_null() || category != other_category))
+ base::Optional<StringId> other_category = slices->category()[slice_idx];
+ if (!category.is_null() && (!other_category || other_category->is_null() ||
+ category != other_category)) {
continue;
- const StringId& other_name = slices->name()[slice_idx];
- if (!name.is_null() && !other_name.is_null() && name != other_name)
+ }
+ base::Optional<StringId> other_name = slices->name()[slice_idx];
+ if (!name.is_null() && other_name && !other_name->is_null() &&
+ name != other_name) {
continue;
+ }
return static_cast<uint32_t>(i);
}
return base::nullopt;
@@ -357,8 +360,8 @@
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());
+ hash.Update(slices.category()[slice_idx].value_or(kNullStringId).raw_id());
+ hash.Update(slices.name()[slice_idx].value_or(kNullStringId).raw_id());
}
// For clients which don't have an integer type (i.e. Javascript), returning
diff --git a/src/trace_processor/importers/common/slice_tracker_unittest.cc b/src/trace_processor/importers/common/slice_tracker_unittest.cc
index 23e2bcf..cb6e579 100644
--- a/src/trace_processor/importers/common/slice_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/slice_tracker_unittest.cc
@@ -66,8 +66,8 @@
EXPECT_EQ(slices.ts()[0], 2);
EXPECT_EQ(slices.dur()[0], 8);
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.category()[0].value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(slices.name()[0].value_or(kNullStringId).raw_id(), 1u);
EXPECT_EQ(slices.depth()[0], 0u);
EXPECT_EQ(slices.arg_set_id()[0], kInvalidArgSetId);
}
@@ -88,8 +88,8 @@
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.category()[0].value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(slices.name()[0].value_or(kNullStringId).raw_id(), 1u);
EXPECT_EQ(slices.depth()[0], 0u);
EXPECT_EQ(slices.arg_set_id()[0], kInvalidArgSetId);
}
@@ -121,8 +121,8 @@
EXPECT_EQ(slices.ts()[0], 2);
EXPECT_EQ(slices.dur()[0], 8);
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.category()[0].value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(slices.name()[0].value_or(kNullStringId).raw_id(), 1u);
EXPECT_EQ(slices.depth()[0], 0u);
auto set_id = slices.arg_set_id()[0];
@@ -158,15 +158,15 @@
EXPECT_EQ(slices.ts()[idx], 2);
EXPECT_EQ(slices.dur()[idx], 8);
EXPECT_EQ(slices.track_id()[idx], track);
- EXPECT_EQ(slices.category()[idx].raw_id(), 0u);
- EXPECT_EQ(slices.name()[idx].raw_id(), 1u);
+ EXPECT_EQ(slices.category()[idx].value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(slices.name()[idx].value_or(kNullStringId).raw_id(), 1u);
EXPECT_EQ(slices.depth()[idx++], 0u);
EXPECT_EQ(slices.ts()[idx], 3);
EXPECT_EQ(slices.dur()[idx], 2);
EXPECT_EQ(slices.track_id()[idx], track);
- EXPECT_EQ(slices.category()[idx].raw_id(), 0u);
- EXPECT_EQ(slices.name()[idx].raw_id(), 2u);
+ EXPECT_EQ(slices.category()[idx].value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(slices.name()[idx].value_or(kNullStringId).raw_id(), 2u);
EXPECT_EQ(slices.depth()[idx], 1u);
EXPECT_EQ(slices.parent_stack_id()[0], 0);
diff --git a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
index cb0d50e..808d7bd 100644
--- a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
@@ -617,7 +617,7 @@
},
{
"cgroup_attach_task",
- 5,
+ 7,
{
{},
{"dst_root", ProtoSchemaType::kInt32},
@@ -625,6 +625,8 @@
{"pid", ProtoSchemaType::kInt32},
{"comm", ProtoSchemaType::kString},
{"cname", ProtoSchemaType::kString},
+ {"dst_level", ProtoSchemaType::kInt32},
+ {"dst_path", ProtoSchemaType::kString},
},
},
{
diff --git a/src/trace_processor/importers/ftrace/ftrace_module_impl.cc b/src/trace_processor/importers/ftrace/ftrace_module_impl.cc
index 7464db5..2299c17 100644
--- a/src/trace_processor/importers/ftrace/ftrace_module_impl.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_module_impl.cc
@@ -43,9 +43,8 @@
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);
- return ModuleResult::Handled();
+ return tokenizer_.TokenizeFtraceBundle(
+ packet->slice(fld_off, ftrace_field.size), seq_state);
}
return ModuleResult::Ignored();
}
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 654b332..425a0ed 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -245,8 +245,8 @@
// 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.
+ // 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())) {
storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
@@ -646,9 +646,9 @@
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 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(
@@ -812,6 +812,13 @@
}
uint32_t tgid = static_cast<uint32_t>(evt.pid());
+ // For kernel counter events, they will become thread counter tracks.
+ // But, we want to use the pid field specified in the event as the thread ID
+ // of the thread_counter_track instead of using the thread ID that emitted
+ // the events. So here, we need to override pid = tgid.
+ if (static_cast<char>(evt.type()) == 'C') {
+ pid = tgid;
+ }
SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
evt.name(), tgid, evt.value());
@@ -828,6 +835,13 @@
}
uint32_t tgid = static_cast<uint32_t>(evt.pid());
+ // For kernel counter events, they will become thread counter tracks.
+ // But, we want to use the pid field specified in the event as the thread ID
+ // of the thread_counter_track instead of using the thread ID that emitted
+ // the events. So here, we need to override pid = tgid.
+ if (static_cast<char>(evt.type()) == 'C') {
+ pid = tgid;
+ }
SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
evt.name(), tgid, evt.value());
@@ -1013,8 +1027,9 @@
auto pid = static_cast<uint32_t>(lmk.pid());
auto opt_utid = context_->process_tracker->GetThreadOrNull(pid);
- // Don't add LMK events for threads we've never seen before. This works around
- // the case where we get an LMK event after a thread has already been killed.
+ // Don't add LMK events for threads we've never seen before. This works
+ // around the case where we get an LMK event after a thread has already been
+ // killed.
if (!opt_utid)
return;
@@ -1107,10 +1122,12 @@
static const uint32_t kCloneThread = 0x00010000; // From kernel's sched.h.
// If the process is a fork, start a new process except if the source tid is
- // kthreadd in which case just make it a new thread associated with kthreadd.
+ // 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(timestamp, source_tid, new_tid, new_comm,
+ ThreadNamePriority::kFtrace);
return;
}
@@ -1132,9 +1149,8 @@
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->UpdateProcessNameFromThreadName(tid, comm);
+ context_->process_tracker->UpdateThreadNameAndMaybeProcessName(
+ tid, comm, ThreadNamePriority::kFtrace);
}
void FtraceParser::ParseBinderTransaction(int64_t timestamp,
@@ -1371,9 +1387,26 @@
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);
+ // It's possible for GpuMemTotal ftrace events to be emitted by kworker
+ // threads *after* process death. In this case, we simply want to discard
+ // the event as otherwise we would create fake processes which we
+ // definitely want to avoid.
+ // See b/192274404 for more info.
+ base::Optional<UniqueTid> opt_utid =
+ context_->process_tracker->GetThreadOrNull(pid);
+ if (!opt_utid)
+ return;
+
+ // If the thread does exist, the |pid| in gpu_mem_total events is always a
+ // true process id (and not a thread id) so ensure there is an association
+ // between the tid and pid.
+ UniqueTid updated_utid = context_->process_tracker->UpdateThread(pid, pid);
+ PERFETTO_DCHECK(updated_utid == *opt_utid);
+
+ // UpdateThread above should ensure this is always set.
+ UniquePid upid = *context_->storage->thread_table().upid()[*opt_utid];
+ PERFETTO_DCHECK(context_->storage->process_table().pid()[upid] == pid);
+
track = context_->track_tracker->InternProcessCounterTrack(
gpu_mem_total_name_id_, upid, gpu_mem_total_unit_id_,
gpu_mem_total_proc_desc_id_);
diff --git a/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc b/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
index e51545d..7253e8a 100644
--- a/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
@@ -23,6 +23,7 @@
#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/trace/ftrace/ftrace_event.pbzero.h"
#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
@@ -33,53 +34,86 @@
using protozero::proto_utils::MakeTagVarInt;
using protozero::proto_utils::ParseVarInt;
+using protos::pbzero::BuiltinClock;
+using protos::pbzero::FtraceClock;
+using protos::pbzero::FtraceEventBundle;
+
+namespace {
+
+PERFETTO_ALWAYS_INLINE base::Optional<int64_t> ResolveTraceTime(
+ TraceProcessorContext* context,
+ ClockTracker::ClockId clock_id,
+ int64_t ts) {
+ // On most traces (i.e. P+), the clock should be BOOTTIME.
+ if (PERFETTO_LIKELY(clock_id == BuiltinClock::BUILTIN_CLOCK_BOOTTIME))
+ return ts;
+ return context->clock_tracker->ToTraceTime(clock_id, ts);
+}
+
+} // namespace
+
PERFETTO_ALWAYS_INLINE
-void FtraceTokenizer::TokenizeFtraceBundle(TraceBlobView bundle,
- PacketSequenceState* state) {
+base::Status FtraceTokenizer::TokenizeFtraceBundle(TraceBlobView bundle,
+ PacketSequenceState* state) {
protos::pbzero::FtraceEventBundle::Decoder decoder(bundle.data(),
bundle.length());
if (PERFETTO_UNLIKELY(!decoder.has_cpu())) {
PERFETTO_ELOG("CPU field not found in FtraceEventBundle");
context_->storage->IncrementStats(stats::ftrace_bundle_tokenizer_errors);
- return;
+ return base::OkStatus();
}
uint32_t cpu = decoder.cpu();
if (PERFETTO_UNLIKELY(cpu > kMaxCpus)) {
PERFETTO_ELOG("CPU larger than kMaxCpus (%u > %zu)", cpu, kMaxCpus);
- return;
+ return base::OkStatus();
+ }
+
+ ClockTracker::ClockId clock_id;
+ switch (decoder.ftrace_clock()) {
+ case FtraceClock::FTRACE_CLOCK_UNSPECIFIED:
+ clock_id = BuiltinClock::BUILTIN_CLOCK_BOOTTIME;
+ break;
+ case FtraceClock::FTRACE_CLOCK_GLOBAL:
+ clock_id = BuiltinClock::BUILTIN_CLOCK_MONOTONIC;
+ break;
+ case FtraceClock::FTRACE_CLOCK_LOCAL:
+ return util::ErrStatus("Unable to parse ftrace packets with local clock");
+ default:
+ return util::ErrStatus(
+ "Unable to parse ftrace packets with unknown clock");
}
if (decoder.has_compact_sched()) {
- TokenizeFtraceCompactSched(cpu, decoder.compact_sched().data,
- decoder.compact_sched().size);
+ TokenizeFtraceCompactSched(cpu, clock_id, decoder.compact_sched());
}
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);
+ size_t off = bundle.offset_of(it->data());
+ TokenizeFtraceEvent(cpu, clock_id, bundle.slice(off, it->size()), state);
}
- context_->sorter->FinalizeFtraceEventBatch(cpu);
+ return base::OkStatus();
}
PERFETTO_ALWAYS_INLINE
void FtraceTokenizer::TokenizeFtraceEvent(uint32_t cpu,
+ ClockTracker::ClockId clock_id,
TraceBlobView event,
PacketSequenceState* state) {
constexpr auto kTimestampFieldNumber =
protos::pbzero::FtraceEvent::kTimestampFieldNumber;
+ constexpr auto kTimestampFieldTag = MakeTagVarInt(kTimestampFieldNumber);
+
const uint8_t* data = event.data();
const size_t length = event.length();
ProtoDecoder decoder(data, length);
- uint64_t raw_timestamp = 0;
- bool timestamp_found = false;
// Speculate on the fact that the timestamp is often the 1st field of the
// event.
- constexpr auto timestampFieldTag = MakeTagVarInt(kTimestampFieldNumber);
- if (PERFETTO_LIKELY(length > 10 && data[0] == timestampFieldTag)) {
+ uint64_t raw_timestamp = 0;
+ bool timestamp_found = false;
+ if (PERFETTO_LIKELY(length > 10 && data[0] == kTimestampFieldTag)) {
// Fastpath.
const uint8_t* next = ParseVarInt(data + 1, data + 11, &raw_timestamp);
timestamp_found = next != data + 1;
@@ -98,18 +132,22 @@
return;
}
- // 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);
+ // ClockTracker will increment some error stats if it failed to convert the
+ // timestamp so just return.
+ int64_t int64_timestamp = static_cast<int64_t>(raw_timestamp);
+ base::Optional<int64_t> timestamp =
+ ResolveTraceTime(context_, clock_id, int64_timestamp);
+ if (!timestamp)
+ return;
+ context_->sorter->PushFtraceEvent(cpu, *timestamp, std::move(event), state);
}
PERFETTO_ALWAYS_INLINE
void FtraceTokenizer::TokenizeFtraceCompactSched(uint32_t cpu,
- const uint8_t* data,
- size_t size) {
- protos::pbzero::FtraceEventBundle::CompactSched::Decoder compact_sched(data,
- size);
+ ClockTracker::ClockId clock_id,
+ protozero::ConstBytes packet) {
+ FtraceEventBundle::CompactSched::Decoder compact_sched(packet);
+
// Build the interning table for comm fields.
std::vector<StringId> string_table;
string_table.reserve(512);
@@ -118,13 +156,14 @@
string_table.push_back(value);
}
- TokenizeFtraceCompactSchedSwitch(cpu, compact_sched, string_table);
- TokenizeFtraceCompactSchedWaking(cpu, compact_sched, string_table);
+ TokenizeFtraceCompactSchedSwitch(cpu, clock_id, compact_sched, string_table);
+ TokenizeFtraceCompactSchedWaking(cpu, clock_id, compact_sched, string_table);
}
void FtraceTokenizer::TokenizeFtraceCompactSchedSwitch(
uint32_t cpu,
- const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
+ ClockTracker::ClockId clock_id,
+ const FtraceEventBundle::CompactSched::Decoder& compact,
const std::vector<StringId>& string_table) {
// Accumulator for timestamp deltas.
int64_t timestamp_acc = 0;
@@ -154,7 +193,11 @@
event.next_pid = *npid_it;
event.next_prio = *nprio_it;
- context_->sorter->PushInlineFtraceEvent(cpu, event_timestamp, event);
+ base::Optional<int64_t> timestamp =
+ ResolveTraceTime(context_, clock_id, event_timestamp);
+ if (!timestamp)
+ return;
+ context_->sorter->PushInlineFtraceEvent(cpu, *timestamp, event);
}
// Check that all packed buffers were decoded correctly, and fully.
@@ -166,7 +209,8 @@
void FtraceTokenizer::TokenizeFtraceCompactSchedWaking(
uint32_t cpu,
- const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
+ ClockTracker::ClockId clock_id,
+ const FtraceEventBundle::CompactSched::Decoder& compact,
const std::vector<StringId>& string_table) {
// Accumulator for timestamp deltas.
int64_t timestamp_acc = 0;
@@ -197,7 +241,11 @@
event.target_cpu = *tcpu_it;
event.prio = *prio_it;
- context_->sorter->PushInlineFtraceEvent(cpu, event_timestamp, event);
+ base::Optional<int64_t> timestamp =
+ ResolveTraceTime(context_, clock_id, event_timestamp);
+ if (!timestamp)
+ return;
+ context_->sorter->PushInlineFtraceEvent(cpu, *timestamp, event);
}
// Check that all packed buffers were decoded correctly, and fully.
diff --git a/src/trace_processor/importers/ftrace/ftrace_tokenizer.h b/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
index 8f95fca..5c53a96 100644
--- a/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
+++ b/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
@@ -18,6 +18,7 @@
#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/clock_tracker.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/util/trace_blob_view.h"
@@ -32,21 +33,24 @@
explicit FtraceTokenizer(TraceProcessorContext* context)
: context_(context) {}
- void TokenizeFtraceBundle(TraceBlobView bundle, PacketSequenceState*);
+ base::Status TokenizeFtraceBundle(TraceBlobView bundle, PacketSequenceState*);
private:
void TokenizeFtraceEvent(uint32_t cpu,
+ ClockTracker::ClockId,
TraceBlobView event,
PacketSequenceState*);
void TokenizeFtraceCompactSched(uint32_t cpu,
- const uint8_t* data,
- size_t size);
+ ClockTracker::ClockId,
+ protozero::ConstBytes);
void TokenizeFtraceCompactSchedSwitch(
uint32_t cpu,
+ ClockTracker::ClockId,
const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
const std::vector<StringId>& string_table);
void TokenizeFtraceCompactSchedWaking(
uint32_t cpu,
+ ClockTracker::ClockId,
const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
const std::vector<StringId>& string_table);
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
index a78e896..a142916 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
+++ b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
@@ -16,7 +16,7 @@
#include "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h"
-#include <inttypes.h>
+#include <cinttypes>
#include <unordered_map>
#include "perfetto/base/logging.h"
diff --git a/src/trace_processor/importers/json/json_trace_parser.cc b/src/trace_processor/importers/json/json_trace_parser.cc
index 85de296..cc9f76f 100644
--- a/src/trace_processor/importers/json/json_trace_parser.cc
+++ b/src/trace_processor/importers/json/json_trace_parser.cc
@@ -16,12 +16,12 @@
#include "src/trace_processor/importers/json/json_trace_parser.h"
-#include <inttypes.h>
-
+#include <cinttypes>
#include <limits>
#include <string>
#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/utils.h"
@@ -32,6 +32,7 @@
#include "src/trace_processor/importers/common/track_tracker.h"
#include "src/trace_processor/importers/json/json_tracker.h"
#include "src/trace_processor/importers/json/json_utils.h"
+#include "src/trace_processor/tables/slice_tables.h"
#include "src/trace_processor/types/trace_processor_context.h"
namespace perfetto {
@@ -126,16 +127,52 @@
inserter);
}
};
+
+ // Only used for 'B', 'E', and 'X' events so wrap in lambda so it gets
+ // ignored in other cases. This lambda is only safe to call within the
+ // scope of this function due to the capture by reference.
+ auto make_thread_slice_row = [&](TrackId track_id) {
+ tables::ThreadSliceTable::Row row;
+ row.ts = timestamp;
+ row.track_id = track_id;
+ row.category = cat_id;
+ row.name = name_id;
+ row.thread_ts =
+ JsonTracker::GetOrCreate(context_)->CoerceToTs(value["tts"]);
+ // tdur will only exist on 'X' events.
+ row.thread_dur =
+ JsonTracker::GetOrCreate(context_)->CoerceToTs(value["tdur"]);
+ // JSON traces don't report these counters as part of slices.
+ row.thread_instruction_count = base::nullopt;
+ row.thread_instruction_delta = base::nullopt;
+ return row;
+ };
+
switch (phase) {
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);
+ slice_tracker->BeginTyped(storage->mutable_thread_slice_table(),
+ make_thread_slice_row(track_id), args_inserter);
MaybeAddFlow(track_id, value);
break;
}
case 'E': { // TRACE_EVENT_END.
TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
- slice_tracker->End(timestamp, track_id, cat_id, name_id, args_inserter);
+ auto opt_slice_id = slice_tracker->End(timestamp, track_id, cat_id,
+ name_id, args_inserter);
+ // Now try to update thread_dur if we have a tts field.
+ auto opt_tts =
+ JsonTracker::GetOrCreate(context_)->CoerceToTs(value["tts"]);
+ if (opt_slice_id.has_value() && opt_tts) {
+ auto* thread_slice = storage->mutable_thread_slice_table();
+ auto maybe_row = thread_slice->id().IndexOf(*opt_slice_id);
+ PERFETTO_DCHECK(maybe_row.has_value());
+ auto start_tts = thread_slice->thread_ts()[*maybe_row];
+ if (start_tts) {
+ thread_slice->mutable_thread_dur()->Set(*maybe_row,
+ *opt_tts - *start_tts);
+ }
+ }
break;
}
case 'X': { // TRACE_EVENT (scoped event).
@@ -144,8 +181,10 @@
if (!opt_dur.has_value())
return;
TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
- slice_tracker->Scoped(timestamp, track_id, cat_id, name_id,
- opt_dur.value(), args_inserter);
+ auto row = make_thread_slice_row(track_id);
+ row.dur = opt_dur.value();
+ slice_tracker->ScopedTyped(storage->mutable_thread_slice_table(),
+ std::move(row), args_inserter);
MaybeAddFlow(track_id, value);
break;
}
@@ -162,13 +201,25 @@
}
for (auto it = args.begin(); it != args.end(); ++it) {
+ double counter;
+ if (it->isString()) {
+ auto opt = base::CStringToDouble(it->asCString());
+ if (!opt.has_value()) {
+ context_->storage->IncrementStats(stats::json_parser_failure);
+ continue;
+ }
+ counter = opt.value();
+ } else if (it->isNumeric()) {
+ counter = it->asDouble();
+ } else {
+ context_->storage->IncrementStats(stats::json_parser_failure);
+ continue;
+ }
std::string counter_name = counter_name_prefix + " " + it.name();
StringId counter_name_id =
context_->storage->InternString(base::StringView(counter_name));
- TrackId track_id = context_->track_tracker->InternProcessCounterTrack(
- counter_name_id, utid);
- context_->event_tracker->PushCounter(timestamp, it->asDouble(),
- track_id);
+ context_->event_tracker->PushProcessCounterForThread(
+ timestamp, counter, counter_name_id, utid);
}
break;
}
@@ -197,6 +248,15 @@
break;
}
track_id = context_->track_tracker->InternThreadTrack(utid);
+ auto row = make_thread_slice_row(track_id);
+ row.dur = 0;
+ if (row.thread_ts) {
+ // Only set thread_dur to zero if we have a thread_ts.
+ row.thread_dur = 0;
+ }
+ slice_tracker->ScopedTyped(storage->mutable_thread_slice_table(),
+ std::move(row), args_inserter);
+ break;
} else {
context_->storage->IncrementStats(stats::json_parser_failure);
break;
@@ -297,4 +357,3 @@
} // namespace trace_processor
} // namespace perfetto
-
diff --git a/src/trace_processor/importers/json/json_trace_tokenizer.cc b/src/trace_processor/importers/json/json_trace_tokenizer.cc
index aa2b259..280725e 100644
--- a/src/trace_processor/importers/json/json_trace_tokenizer.cc
+++ b/src/trace_processor/importers/json/json_trace_tokenizer.cc
@@ -58,9 +58,12 @@
case 't':
key->push_back('\t');
break;
+ case 'u':
+ // Just pass through \uxxxx escape sequences which JSON supports but is
+ // not worth the effort to parse as we never use them here.
+ key->append("\\u");
+ break;
default:
- // We don't support any other escape sequences (concretely \uxxxx
- // which JSON supports but is too much effort for us to parse).
return util::ErrStatus("Illegal character in JSON");
}
} else if (c != '\\') {
@@ -525,6 +528,18 @@
stats::json_display_time_unit_too_late);
}
return ParseInternal(next, end, out);
+ } else if (key == "otherData") {
+ base::StringView unparsed;
+ const auto other = ReadOneJsonDict(next, end, &unparsed, &next);
+ if (other == ReadDictRes::kEndOfArray)
+ return util::ErrStatus(
+ "Failure parsing JSON: Missing ] in otherData");
+ if (other == ReadDictRes::kEndOfTrace)
+ return util::ErrStatus(
+ "Failure parsing JSON: Failed parsing otherData");
+ if (other == ReadDictRes::kNeedsMoreData)
+ return util::ErrStatus("Failure parsing JSON: otherData too large");
+ return ParseInternal(next, end, out);
} else {
// If we don't recognize the key, just ignore the rest of the trace and
// go to EOF.
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
index 9d80101..a52c7fa 100644
--- a/src/trace_processor/importers/memory_tracker/memory_allocator_node_id.cc
+++ b/src/trace_processor/importers/memory_tracker/memory_allocator_node_id.cc
@@ -16,9 +16,10 @@
#include "perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h"
-#include <inttypes.h>
#include <stdio.h>
+#include <cinttypes>
+
#include "perfetto/base/logging.h"
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
index faaf084..73ee3f1 100644
--- a/src/trace_processor/importers/memory_tracker/raw_process_memory_node.cc
+++ b/src/trace_processor/importers/memory_tracker/raw_process_memory_node.cc
@@ -16,10 +16,10 @@
#include "perfetto/ext/trace_processor/importers/memory_tracker/raw_process_memory_node.h"
-#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
+#include <cinttypes>
#include <functional>
#include <memory>
diff --git a/src/trace_processor/importers/proto/flamegraph_construction_algorithms.cc b/src/trace_processor/importers/proto/flamegraph_construction_algorithms.cc
new file mode 100644
index 0000000..5882e12
--- /dev/null
+++ b/src/trace_processor/importers/proto/flamegraph_construction_algorithms.cc
@@ -0,0 +1,383 @@
+/*
+ * 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 "flamegraph_construction_algorithms.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+struct MergedCallsite {
+ StringId frame_name;
+ StringId mapping_name;
+ base::Optional<StringId> source_file;
+ base::Optional<uint32_t> line_number;
+ base::Optional<uint32_t> parent_idx;
+ bool operator<(const MergedCallsite& o) const {
+ return std::tie(frame_name, mapping_name, parent_idx) <
+ std::tie(o.frame_name, o.mapping_name, o.parent_idx);
+ }
+};
+
+struct FlamegraphTableAndMergedCallsites {
+ std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> tbl;
+ std::vector<uint32_t> callsite_to_merged_callsite;
+};
+
+std::vector<MergedCallsite> GetMergedCallsites(TraceStorage* storage,
+ uint32_t callstack_row) {
+ const tables::StackProfileCallsiteTable& callsites_tbl =
+ storage->stack_profile_callsite_table();
+ const tables::StackProfileFrameTable& frames_tbl =
+ storage->stack_profile_frame_table();
+ const tables::SymbolTable& symbols_tbl = storage->symbol_table();
+ const tables::StackProfileMappingTable& mapping_tbl =
+ storage->stack_profile_mapping_table();
+
+ uint32_t frame_idx =
+ *frames_tbl.id().IndexOf(callsites_tbl.frame_id()[callstack_row]);
+
+ uint32_t mapping_idx =
+ *mapping_tbl.id().IndexOf(frames_tbl.mapping()[frame_idx]);
+ StringId mapping_name = mapping_tbl.name()[mapping_idx];
+
+ base::Optional<uint32_t> symbol_set_id =
+ frames_tbl.symbol_set_id()[frame_idx];
+
+ 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, base::nullopt, base::nullopt}};
+ }
+
+ std::vector<MergedCallsite> result;
+ // id == symbol_set_id for the bottommost frame.
+ // TODO(lalitm): Encode this optimization in the table and remove this
+ // custom optimization.
+ uint32_t symbol_set_idx = *symbols_tbl.id().IndexOf(SymbolId(*symbol_set_id));
+ for (uint32_t i = symbol_set_idx;
+ i < symbols_tbl.row_count() &&
+ symbols_tbl.symbol_set_id()[i] == *symbol_set_id;
+ ++i) {
+ result.emplace_back(MergedCallsite{
+ symbols_tbl.name()[i], mapping_name, symbols_tbl.source_file()[i],
+ symbols_tbl.line_number()[i], base::nullopt});
+ }
+ std::reverse(result.begin(), result.end());
+ return result;
+}
+} // namespace
+
+static FlamegraphTableAndMergedCallsites BuildFlamegraphTableTreeStructure(
+ TraceStorage* storage,
+ UniquePid upid,
+ base::Optional<int64_t> timestamp,
+ StringId profile_type) {
+ const tables::StackProfileCallsiteTable& callsites_tbl =
+ storage->stack_profile_callsite_table();
+
+ std::vector<uint32_t> callsite_to_merged_callsite(callsites_tbl.row_count(),
+ 0);
+ std::map<MergedCallsite, uint32_t> merged_callsites_to_table_idx;
+
+ std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> tbl(
+ new tables::ExperimentalFlamegraphNodesTable(
+ storage->mutable_string_pool(), nullptr));
+
+ // FORWARD PASS:
+ // Aggregate callstacks by frame name / mapping name. Use symbolization
+ // data.
+ for (uint32_t i = 0; i < callsites_tbl.row_count(); ++i) {
+ base::Optional<uint32_t> parent_idx;
+
+ 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];
+ }
+
+ auto callsites = GetMergedCallsites(storage, i);
+ // Loop below needs to run at least once for parent_idx to get updated.
+ PERFETTO_CHECK(!callsites.empty());
+ std::map<MergedCallsite, uint32_t> callsites_to_rowid;
+ for (MergedCallsite& merged_callsite : callsites) {
+ merged_callsite.parent_idx = parent_idx;
+ auto it = merged_callsites_to_table_idx.find(merged_callsite);
+ if (it == merged_callsites_to_table_idx.end()) {
+ std::tie(it, std::ignore) = merged_callsites_to_table_idx.emplace(
+ merged_callsite, merged_callsites_to_table_idx.size());
+ tables::ExperimentalFlamegraphNodesTable::Row row{};
+ if (parent_idx) {
+ row.depth = tbl->depth()[*parent_idx] + 1;
+ } else {
+ row.depth = 0;
+ }
+ // For heap profiling, the 'ts' column is always the arbitrary value
+ // inputed in a query of the form below, not the actual time
+ // when the allocation happened:
+ // `select * form experimental_flamegraph(605908369259172, 1, 'native')`
+ // However, removing this value would break the query with constraints
+ // such as the one above because SQLite will do an equality check on the
+ // `ts` column: `ts == 605908369259172`.
+ // TODO(octaviant) find a way of removing this or giving it a meaningful
+ // value
+ if (timestamp) {
+ row.ts = *timestamp;
+ }
+ row.upid = upid;
+ row.profile_type = profile_type;
+ row.name = merged_callsite.frame_name;
+ row.map_name = merged_callsite.mapping_name;
+ if (parent_idx)
+ row.parent_id = tbl->id()[*parent_idx];
+ tbl->Insert(row);
+ callsites_to_rowid[merged_callsite] =
+ static_cast<uint32_t>(merged_callsites_to_table_idx.size() - 1);
+
+ PERFETTO_CHECK(merged_callsites_to_table_idx.size() ==
+ tbl->row_count());
+ } else {
+ MergedCallsite saved_callsite = it->first;
+ callsites_to_rowid.erase(saved_callsite);
+ if (saved_callsite.source_file != merged_callsite.source_file) {
+ saved_callsite.source_file = base::nullopt;
+ }
+ if (saved_callsite.line_number != merged_callsite.line_number) {
+ saved_callsite.line_number = base::nullopt;
+ }
+ callsites_to_rowid[saved_callsite] = it->second;
+ }
+ parent_idx = it->second;
+ }
+
+ for (const auto& it : callsites_to_rowid) {
+ if (it.first.source_file) {
+ tbl->mutable_source_file()->Set(it.second, *it.first.source_file);
+ }
+ if (it.first.line_number) {
+ tbl->mutable_line_number()->Set(it.second, *it.first.line_number);
+ }
+ }
+
+ PERFETTO_CHECK(parent_idx);
+ callsite_to_merged_callsite[i] = *parent_idx;
+ }
+
+ return {std::move(tbl), callsite_to_merged_callsite};
+}
+
+static std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
+BuildFlamegraphTableHeapSizeAndCount(
+ std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> tbl,
+ const std::vector<uint32_t>& callsite_to_merged_callsite,
+ const Table& filtered) {
+ for (auto it = filtered.IterateRows(); it; it.Next()) {
+ int64_t size =
+ it.Get(static_cast<uint32_t>(
+ tables::HeapProfileAllocationTable::ColumnIndex::size))
+ .long_value;
+ int64_t count =
+ it.Get(static_cast<uint32_t>(
+ tables::HeapProfileAllocationTable::ColumnIndex::count))
+ .long_value;
+ int64_t callsite_id =
+ it
+ .Get(static_cast<uint32_t>(
+ tables::HeapProfileAllocationTable::ColumnIndex::callsite_id))
+ .long_value;
+
+ PERFETTO_CHECK((size <= 0 && count <= 0) || (size >= 0 && count >= 0));
+ uint32_t merged_idx =
+ callsite_to_merged_callsite[static_cast<unsigned long>(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) {
+ 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);
+ }
+
+ tbl->mutable_size()->Set(merged_idx, tbl->size()[merged_idx] + size);
+ tbl->mutable_count()->Set(merged_idx, tbl->count()[merged_idx] + count);
+ }
+
+ // BACKWARD PASS:
+ // Propagate sizes to parents.
+ for (int64_t i = tbl->row_count() - 1; i >= 0; --i) {
+ auto idx = static_cast<uint32_t>(i);
+
+ tbl->mutable_cumulative_size()->Set(
+ idx, tbl->cumulative_size()[idx] + tbl->size()[idx]);
+ tbl->mutable_cumulative_count()->Set(
+ idx, tbl->cumulative_count()[idx] + tbl->count()[idx]);
+
+ tbl->mutable_cumulative_alloc_size()->Set(
+ idx, tbl->cumulative_alloc_size()[idx] + tbl->alloc_size()[idx]);
+ tbl->mutable_cumulative_alloc_count()->Set(
+ idx, tbl->cumulative_alloc_count()[idx] + tbl->alloc_count()[idx]);
+
+ auto parent = tbl->parent_id()[idx];
+ if (parent) {
+ uint32_t parent_idx = *tbl->id().IndexOf(
+ tables::ExperimentalFlamegraphNodesTable::Id(*parent));
+ tbl->mutable_cumulative_size()->Set(
+ parent_idx,
+ tbl->cumulative_size()[parent_idx] + tbl->cumulative_size()[idx]);
+ tbl->mutable_cumulative_count()->Set(
+ parent_idx,
+ tbl->cumulative_count()[parent_idx] + tbl->cumulative_count()[idx]);
+
+ tbl->mutable_cumulative_alloc_size()->Set(
+ parent_idx, tbl->cumulative_alloc_size()[parent_idx] +
+ tbl->cumulative_alloc_size()[idx]);
+ tbl->mutable_cumulative_alloc_count()->Set(
+ parent_idx, tbl->cumulative_alloc_count()[parent_idx] +
+ tbl->cumulative_alloc_count()[idx]);
+ }
+ }
+
+ return tbl;
+}
+
+static std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
+BuildFlamegraphTableCallstackSizeAndCount(
+ std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> tbl,
+ const std::vector<uint32_t>& callsite_to_merged_callsite,
+ const Table& filtered) {
+ for (auto it = filtered.IterateRows(); it; it.Next()) {
+ int64_t callsite_id =
+ it.Get(static_cast<uint32_t>(
+ tables::PerfSampleTable::ColumnIndex::callsite_id))
+ .long_value;
+ int64_t ts =
+ it.Get(static_cast<uint32_t>(tables::PerfSampleTable::ColumnIndex::ts))
+ .long_value;
+
+ uint32_t merged_idx =
+ callsite_to_merged_callsite[static_cast<unsigned long>(callsite_id)];
+ tbl->mutable_size()->Set(merged_idx, tbl->size()[merged_idx] + 1);
+ tbl->mutable_count()->Set(merged_idx, tbl->count()[merged_idx] + 1);
+ tbl->mutable_ts()->Set(merged_idx, ts);
+ }
+
+ // BACKWARD PASS:
+ // Propagate sizes to parents.
+ for (int64_t i = tbl->row_count() - 1; i >= 0; --i) {
+ auto idx = static_cast<uint32_t>(i);
+
+ tbl->mutable_cumulative_size()->Set(
+ idx, tbl->cumulative_size()[idx] + tbl->size()[idx]);
+ tbl->mutable_cumulative_count()->Set(
+ idx, tbl->cumulative_count()[idx] + tbl->count()[idx]);
+
+ auto parent = tbl->parent_id()[idx];
+ if (parent) {
+ uint32_t parent_idx = *tbl->id().IndexOf(
+ tables::ExperimentalFlamegraphNodesTable::Id(*parent));
+ tbl->mutable_cumulative_size()->Set(
+ parent_idx,
+ tbl->cumulative_size()[parent_idx] + tbl->cumulative_size()[idx]);
+ tbl->mutable_cumulative_count()->Set(
+ parent_idx,
+ tbl->cumulative_count()[parent_idx] + tbl->cumulative_count()[idx]);
+ }
+ }
+ return tbl;
+}
+
+std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
+BuildNativeHeapProfileFlamegraph(TraceStorage* storage,
+ UniquePid upid,
+ int64_t timestamp) {
+ const tables::HeapProfileAllocationTable& allocation_tbl =
+ storage->heap_profile_allocation_table();
+ // PASS OVER ALLOCATIONS:
+ // Aggregate allocations into the newly built tree.
+ auto filtered = allocation_tbl.Filter(
+ {allocation_tbl.ts().le(timestamp), allocation_tbl.upid().eq(upid)});
+ if (filtered.row_count() == 0) {
+ return nullptr;
+ }
+ StringId profile_type = storage->InternString("native");
+ FlamegraphTableAndMergedCallsites table_and_callsites =
+ BuildFlamegraphTableTreeStructure(
+ storage, upid, base::make_optional(timestamp), profile_type);
+ return BuildFlamegraphTableHeapSizeAndCount(
+ std::move(table_and_callsites.tbl),
+ table_and_callsites.callsite_to_merged_callsite, filtered);
+}
+
+std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
+BuildNativeCallStackSamplingFlamegraph(
+ TraceStorage* storage,
+ UniquePid upid,
+ const std::vector<TimeConstraints>& time_constraints) {
+ // 1.Create set of all utids mapped to the given upid
+ std::set<tables::ThreadTable::Id> utids;
+ RowMap threads_in_pid_rm = storage->thread_table().FilterToRowMap(
+ {storage->thread_table().upid().eq(upid)});
+ for (auto it = threads_in_pid_rm.IterateRows(); it; it.Next()) {
+ utids.insert(storage->thread_table().id()[it.row()]);
+ }
+
+ // 2.Get all row indices in perf_sample that correspond to the requested utids
+ std::vector<uint32_t> cs_rows;
+ for (uint32_t i = 0; i < storage->perf_sample_table().row_count(); ++i) {
+ if (utids.find(static_cast<tables::ThreadTable::Id>(
+ storage->perf_sample_table().utid()[i])) != utids.end()) {
+ cs_rows.push_back(i);
+ }
+ }
+
+ // 3.Filter rows that correspond to the selected utids
+ RowMap filtered_rm = RowMap(std::move(cs_rows));
+ Table filtered = storage->perf_sample_table().Apply(std::move(filtered_rm));
+
+ // 4.Filter rows by time constraints
+ for (const auto& tc : time_constraints) {
+ if (!(tc.op == FilterOp::kGt || tc.op == FilterOp::kLt ||
+ tc.op == FilterOp::kGe || tc.op == FilterOp::kLe)) {
+ PERFETTO_FATAL("Filter operation %d not permitted for perf.", tc.op);
+ }
+ Constraint cs = Constraint{
+ static_cast<uint32_t>(tables::PerfSampleTable::ColumnIndex::ts), tc.op,
+ SqlValue::Long(tc.value)};
+ filtered = filtered.Filter({cs});
+ }
+
+ if (filtered.row_count() == 0) {
+ return nullptr;
+ }
+ StringId profile_type = storage->InternString("perf");
+ FlamegraphTableAndMergedCallsites table_and_callsites =
+ BuildFlamegraphTableTreeStructure(storage, upid, base::nullopt,
+ profile_type);
+ return BuildFlamegraphTableCallstackSizeAndCount(
+ std::move(table_and_callsites.tbl),
+ table_and_callsites.callsite_to_merged_callsite, filtered);
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/flamegraph_construction_algorithms.h b/src/trace_processor/importers/proto/flamegraph_construction_algorithms.h
new file mode 100644
index 0000000..f5cf8b1
--- /dev/null
+++ b/src/trace_processor/importers/proto/flamegraph_construction_algorithms.h
@@ -0,0 +1,46 @@
+/*
+ * 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_FLAMEGRAPH_CONSTRUCTION_ALGORITHMS_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_FLAMEGRAPH_CONSTRUCTION_ALGORITHMS_H_
+
+#include <set>
+
+#include "src/trace_processor/storage/trace_storage.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Represents a time boundary for a column.
+struct TimeConstraints {
+ FilterOp op;
+ int64_t value;
+};
+
+std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
+BuildNativeHeapProfileFlamegraph(TraceStorage* storage,
+ UniquePid upid,
+ int64_t timestamp);
+
+std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
+BuildNativeCallStackSamplingFlamegraph(
+ TraceStorage* storage,
+ UniquePid upid,
+ const std::vector<TimeConstraints>& time_constraints);
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_FLAMEGRAPH_CONSTRUCTION_ALGORITHMS_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
index f52931f..70efab4 100644
--- a/src/trace_processor/importers/proto/frame_timeline_event_parser.cc
+++ b/src/trace_processor/importers/proto/frame_timeline_event_parser.cc
@@ -16,7 +16,7 @@
#include "src/trace_processor/importers/proto/frame_timeline_event_parser.h"
-#include <inttypes.h>
+#include <cinttypes>
#include "perfetto/ext/base/utils.h"
#include "perfetto/protozero/field.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..8211b6c 100644
--- a/src/trace_processor/importers/proto/gpu_event_parser.cc
+++ b/src/trace_processor/importers/proto/gpu_event_parser.cc
@@ -16,7 +16,7 @@
#include "src/trace_processor/importers/proto/gpu_event_parser.h"
-#include <inttypes.h>
+#include <cinttypes>
#include "perfetto/ext/base/utils.h"
#include "perfetto/protozero/field.h"
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..aa6742e 100644
--- a/src/trace_processor/importers/proto/graphics_frame_event_parser.cc
+++ b/src/trace_processor/importers/proto/graphics_frame_event_parser.cc
@@ -16,7 +16,7 @@
#include "src/trace_processor/importers/proto/graphics_frame_event_parser.h"
-#include <inttypes.h>
+#include <cinttypes>
#include "perfetto/ext/base/utils.h"
#include "perfetto/protozero/field.h"
diff --git a/src/trace_processor/importers/proto/heap_profile_tracker.cc b/src/trace_processor/importers/proto/heap_profile_tracker.cc
index 45a5c7b..ea20108 100644
--- a/src/trace_processor/importers/proto/heap_profile_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_profile_tracker.cc
@@ -26,239 +26,10 @@
namespace perfetto {
namespace trace_processor {
-namespace {
-struct MergedCallsite {
- StringId frame_name;
- StringId mapping_name;
- base::Optional<StringId> source_file;
- base::Optional<uint32_t> line_number;
- base::Optional<uint32_t> parent_idx;
- bool operator<(const MergedCallsite& o) const {
- return std::tie(frame_name, mapping_name, parent_idx) <
- std::tie(o.frame_name, o.mapping_name, o.parent_idx);
- }
-};
-
-std::vector<MergedCallsite> GetMergedCallsites(TraceStorage* storage,
- uint32_t callstack_row) {
- const tables::StackProfileCallsiteTable& callsites_tbl =
- storage->stack_profile_callsite_table();
- const tables::StackProfileFrameTable& frames_tbl =
- storage->stack_profile_frame_table();
- const tables::SymbolTable& symbols_tbl = storage->symbol_table();
- const tables::StackProfileMappingTable& mapping_tbl =
- storage->stack_profile_mapping_table();
-
- uint32_t frame_idx =
- *frames_tbl.id().IndexOf(callsites_tbl.frame_id()[callstack_row]);
-
- uint32_t mapping_idx =
- *mapping_tbl.id().IndexOf(frames_tbl.mapping()[frame_idx]);
- StringId mapping_name = mapping_tbl.name()[mapping_idx];
-
- base::Optional<uint32_t> symbol_set_id =
- frames_tbl.symbol_set_id()[frame_idx];
-
- 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, base::nullopt, base::nullopt}};
- }
-
- std::vector<MergedCallsite> result;
- // id == symbol_set_id for the bottommost frame.
- // TODO(lalitm): Encode this optimization in the table and remove this
- // custom optimization.
- uint32_t symbol_set_idx = *symbols_tbl.id().IndexOf(SymbolId(*symbol_set_id));
- for (uint32_t i = symbol_set_idx;
- i < symbols_tbl.row_count() &&
- symbols_tbl.symbol_set_id()[i] == *symbol_set_id;
- ++i) {
- result.emplace_back(MergedCallsite{
- symbols_tbl.name()[i], mapping_name, symbols_tbl.source_file()[i],
- symbols_tbl.line_number()[i], base::nullopt});
- }
- std::reverse(result.begin(), result.end());
- return result;
-}
-} // namespace
-
-std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> BuildNativeFlamegraph(
- TraceStorage* storage,
- UniquePid upid,
- int64_t timestamp) {
- const tables::HeapProfileAllocationTable& allocation_tbl =
- storage->heap_profile_allocation_table();
- const tables::StackProfileCallsiteTable& callsites_tbl =
- storage->stack_profile_callsite_table();
-
- StringId profile_type = storage->InternString("native");
-
- std::vector<uint32_t> callsite_to_merged_callsite(callsites_tbl.row_count(),
- 0);
- std::map<MergedCallsite, uint32_t> merged_callsites_to_table_idx;
-
- std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> tbl(
- new tables::ExperimentalFlamegraphNodesTable(
- storage->mutable_string_pool(), nullptr));
-
- // FORWARD PASS:
- // Aggregate callstacks by frame name / mapping name. Use symbolization
- // data.
- for (uint32_t i = 0; i < callsites_tbl.row_count(); ++i) {
- base::Optional<uint32_t> parent_idx;
-
- 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];
- }
-
- auto callsites = GetMergedCallsites(storage, i);
- // Loop below needs to run at least once for parent_idx to get updated.
- PERFETTO_CHECK(!callsites.empty());
- std::map<MergedCallsite, uint32_t> callsites_to_rowid;
- for (MergedCallsite& merged_callsite : callsites) {
- merged_callsite.parent_idx = parent_idx;
- auto it = merged_callsites_to_table_idx.find(merged_callsite);
- if (it == merged_callsites_to_table_idx.end()) {
- std::tie(it, std::ignore) = merged_callsites_to_table_idx.emplace(
- merged_callsite, merged_callsites_to_table_idx.size());
- tables::ExperimentalFlamegraphNodesTable::Row row{};
- if (parent_idx) {
- row.depth = tbl->depth()[*parent_idx] + 1;
- } else {
- row.depth = 0;
- }
- row.ts = timestamp;
- row.upid = upid;
- row.profile_type = profile_type;
- row.name = merged_callsite.frame_name;
- row.map_name = merged_callsite.mapping_name;
- if (parent_idx)
- row.parent_id = tbl->id()[*parent_idx];
- parent_idx = tbl->Insert(std::move(row)).row;
- callsites_to_rowid[merged_callsite] =
- static_cast<uint32_t>(merged_callsites_to_table_idx.size());
-
- PERFETTO_CHECK(merged_callsites_to_table_idx.size() ==
- tbl->row_count());
- } else {
- MergedCallsite saved_callsite = it->first;
- callsites_to_rowid.erase(saved_callsite);
- if (saved_callsite.source_file != merged_callsite.source_file) {
- saved_callsite.source_file = base::nullopt;
- }
- if (saved_callsite.line_number != merged_callsite.line_number) {
- saved_callsite.line_number = base::nullopt;
- }
- callsites_to_rowid[saved_callsite] = it->second;
- }
- parent_idx = it->second;
- }
-
- for (const auto& it : callsites_to_rowid) {
- if (it.first.source_file) {
- tbl->mutable_source_file()->Set(it.second, *it.first.source_file);
- }
- if (it.first.line_number) {
- tbl->mutable_line_number()->Set(it.second, *it.first.line_number);
- }
- }
-
- PERFETTO_CHECK(parent_idx);
- callsite_to_merged_callsite[i] = *parent_idx;
- }
-
- // PASS OVER ALLOCATIONS:
- // Aggregate allocations into the newly built tree.
- auto filtered = allocation_tbl.Filter(
- {allocation_tbl.ts().le(timestamp), allocation_tbl.upid().eq(upid)});
-
- if (filtered.row_count() == 0) {
- return nullptr;
- }
-
- for (auto it = filtered.IterateRows(); it; it.Next()) {
- int64_t size =
- it.Get(static_cast<uint32_t>(
- tables::HeapProfileAllocationTable::ColumnIndex::size))
- .long_value;
- int64_t count =
- it.Get(static_cast<uint32_t>(
- tables::HeapProfileAllocationTable::ColumnIndex::count))
- .long_value;
- int64_t callsite_id =
- it
- .Get(static_cast<uint32_t>(
- tables::HeapProfileAllocationTable::ColumnIndex::callsite_id))
- .long_value;
-
- PERFETTO_CHECK((size <= 0 && count <= 0) || (size >= 0 && count >= 0));
- 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) {
- 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);
- }
-
- tbl->mutable_size()->Set(merged_idx, tbl->size()[merged_idx] + size);
- tbl->mutable_count()->Set(merged_idx, tbl->count()[merged_idx] + count);
- }
-
- // BACKWARD PASS:
- // Propagate sizes to parents.
- for (int64_t i = tbl->row_count() - 1; i >= 0; --i) {
- uint32_t idx = static_cast<uint32_t>(i);
-
- tbl->mutable_cumulative_size()->Set(
- idx, tbl->cumulative_size()[idx] + tbl->size()[idx]);
- tbl->mutable_cumulative_count()->Set(
- idx, tbl->cumulative_count()[idx] + tbl->count()[idx]);
-
- tbl->mutable_cumulative_alloc_size()->Set(
- idx, tbl->cumulative_alloc_size()[idx] + tbl->alloc_size()[idx]);
- tbl->mutable_cumulative_alloc_count()->Set(
- idx, tbl->cumulative_alloc_count()[idx] + tbl->alloc_count()[idx]);
-
- auto parent = tbl->parent_id()[idx];
- if (parent) {
- uint32_t parent_idx = *tbl->id().IndexOf(
- tables::ExperimentalFlamegraphNodesTable::Id(*parent));
- tbl->mutable_cumulative_size()->Set(
- parent_idx,
- tbl->cumulative_size()[parent_idx] + tbl->cumulative_size()[idx]);
- tbl->mutable_cumulative_count()->Set(
- parent_idx,
- tbl->cumulative_count()[parent_idx] + tbl->cumulative_count()[idx]);
-
- tbl->mutable_cumulative_alloc_size()->Set(
- parent_idx, tbl->cumulative_alloc_size()[parent_idx] +
- tbl->cumulative_alloc_size()[idx]);
- tbl->mutable_cumulative_alloc_count()->Set(
- parent_idx, tbl->cumulative_alloc_count()[parent_idx] +
- tbl->cumulative_alloc_count()[idx]);
- }
- }
-
- return tbl;
-}
-
HeapProfileTracker::HeapProfileTracker(TraceProcessorContext* context)
- : context_(context), empty_(context_->storage->InternString({"", 0})) {}
+ : context_(context),
+ empty_(context_->storage->InternString({"", 0})),
+ art_heap_(context_->storage->InternString("com.android.art")) {}
HeapProfileTracker::~HeapProfileTracker() = default;
@@ -389,7 +160,12 @@
context_->storage->mutable_heap_profile_allocation_table()->Insert(
alloc_delta);
}
- if (free_delta.count || free_delta.size) {
+
+ // ART only reports allocations, and not frees. This throws off our logic
+ // that assumes that if a new object was allocated with the same address,
+ // the old one has to have been freed in the meantime.
+ // See HeapTracker::RecordMalloc in bookkeeping.cc.
+ if (alloc.heap_name != art_heap_ && (free_delta.count || free_delta.size)) {
context_->storage->mutable_heap_profile_allocation_table()->Insert(
free_delta);
}
diff --git a/src/trace_processor/importers/proto/heap_profile_tracker.h b/src/trace_processor/importers/proto/heap_profile_tracker.h
index 066c238..03b1d7b 100644
--- a/src/trace_processor/importers/proto/heap_profile_tracker.h
+++ b/src/trace_processor/importers/proto/heap_profile_tracker.h
@@ -27,9 +27,6 @@
namespace perfetto {
namespace trace_processor {
-std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
-BuildNativeFlamegraph(TraceStorage* storage, UniquePid upid, int64_t timestamp);
-
class TraceProcessorContext;
class HeapProfileTracker {
@@ -120,6 +117,7 @@
std::map<uint32_t, SequenceState> sequence_state_;
TraceProcessorContext* const context_;
const StringId empty_;
+ const StringId art_heap_;
};
} // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/metadata_module.cc b/src/trace_processor/importers/proto/metadata_module.cc
index b6a082f..b811320 100644
--- a/src/trace_processor/importers/proto/metadata_module.cc
+++ b/src/trace_processor/importers/proto/metadata_module.cc
@@ -31,7 +31,10 @@
using perfetto::protos::pbzero::TracePacket;
MetadataModule::MetadataModule(TraceProcessorContext* context)
- : context_(context) {
+ : context_(context),
+ producer_name_key_id_(context_->storage->InternString("producer_name")),
+ trusted_producer_uid_key_id_(
+ context_->storage->InternString("trusted_producer_uid")) {
RegisterForField(TracePacket::kUiStateFieldNumber, context);
RegisterForField(TracePacket::kChromeMetadataFieldNumber, context);
RegisterForField(TracePacket::kChromeBenchmarkMetadataFieldNumber, context);
@@ -160,15 +163,16 @@
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()));
+ StringId producer_name =
+ context_->storage->InternString(trigger.producer_name());
+ if (!producer_name.is_null()) {
+ args_table->AddArg(producer_name_key_id_,
+ Variadic::String(producer_name));
+ }
+ if (trigger.has_trusted_producer_uid()) {
+ args_table->AddArg(trusted_producer_uid_key_id_,
+ Variadic::Integer(trigger.trusted_producer_uid()));
+ }
});
}
diff --git a/src/trace_processor/importers/proto/metadata_module.h b/src/trace_processor/importers/proto/metadata_module.h
index 55ac666..38a6a56 100644
--- a/src/trace_processor/importers/proto/metadata_module.h
+++ b/src/trace_processor/importers/proto/metadata_module.h
@@ -49,6 +49,8 @@
void ParseTrigger(int64_t ts, ConstBytes);
TraceProcessorContext* context_;
+ StringId producer_name_key_id_ = kNullStringId;
+ StringId trusted_producer_uid_key_id_ = kNullStringId;
};
} // 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..13e9b19 100644
--- a/src/trace_processor/importers/proto/perf_sample_tracker.cc
+++ b/src/trace_processor/importers/proto/perf_sample_tracker.cc
@@ -15,9 +15,10 @@
*/
#include "src/trace_processor/importers/proto/perf_sample_tracker.h"
-#include <inttypes.h>
#include <stdio.h>
+#include <cinttypes>
+
#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"
@@ -45,6 +46,7 @@
default:
break;
}
+ PERFETTO_DLOG("Unknown PerfEvents::Counter enum value");
return "unknown";
}
@@ -55,11 +57,30 @@
PerfSampleDefaults::Decoder perf_defaults(defaults->perf_sample_defaults());
PerfEvents::Timebase::Decoder timebase(perf_defaults.timebase());
- if (timebase.counter() != PerfEvents::UNKNOWN_COUNTER) {
+ auto config_given_name = timebase.name();
+ if (config_given_name.size > 0) {
+ return context->storage->InternString(config_given_name);
+ }
+ if (timebase.has_counter()) {
return context->storage->InternString(StringifyCounter(timebase.counter()));
}
- PerfEvents::Tracepoint::Decoder tracepoint(timebase.tracepoint());
- return context->storage->InternString(tracepoint.name());
+ if (timebase.has_tracepoint()) {
+ PerfEvents::Tracepoint::Decoder tracepoint(timebase.tracepoint());
+ return context->storage->InternString(tracepoint.name());
+ }
+ if (timebase.has_raw_event()) {
+ PerfEvents::RawEvent::Decoder raw(timebase.raw_event());
+ // This doesn't follow any pre-existing naming scheme, but aims to be a
+ // short-enough default that is distinguishable.
+ char buf[128] = {};
+ snprintf(buf, sizeof(buf),
+ "raw.0x%" PRIx32 ".0x%" PRIx64 ".0x%" PRIx64 ".0x%" PRIx64,
+ raw.type(), raw.config(), raw.config1(), raw.config2());
+ return context->storage->InternString(buf);
+ }
+
+ PERFETTO_DLOG("Could not name the perf timebase counter");
+ return context->storage->InternString("unknown");
}
} // namespace
diff --git a/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc b/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc
index 16c65b3..23b1d1d 100644
--- a/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc
+++ b/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc
@@ -150,6 +150,40 @@
ASSERT_EQ(track_name, "cpu-clock");
}
+// Like TimebaseTrackName_Counter, but with a config supplying an explicit name
+// for the counter.
+TEST_F(PerfSampleTrackerTest, TimebaseTrackName_ConfigSuppliedName) {
+ 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_name("test-name");
+ 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]);
+
+ // Using the config-supplied name for the track.
+ std::string track_name =
+ context.storage->GetString(track_table.name()[*row_id]).ToStdString();
+ ASSERT_EQ(track_name, "test-name");
+}
+
} // 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..61b2567 100644
--- a/src/trace_processor/importers/proto/profile_module.cc
+++ b/src/trace_processor/importers/proto/profile_module.cc
@@ -17,12 +17,15 @@
#include "src/trace_processor/importers/proto/profile_module.h"
#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_utils.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/heap_profile_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/trace_storage.h"
#include "src/trace_processor/tables/profiler_tables.h"
@@ -32,7 +35,10 @@
#include "protos/perfetto/common/builtin_clock.pbzero.h"
#include "protos/perfetto/common/perf_events.pbzero.h"
+#include "protos/perfetto/trace/profiling/deobfuscation.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"
namespace perfetto {
namespace trace_processor {
@@ -44,6 +50,11 @@
: context_(context) {
RegisterForField(TracePacket::kStreamingProfilePacketFieldNumber, context);
RegisterForField(TracePacket::kPerfSampleFieldNumber, context);
+ RegisterForField(TracePacket::kProfilePacketFieldNumber, context);
+ RegisterForField(TracePacket::kModuleSymbolsFieldNumber, context);
+ // note: deobfuscation mappings also handled by HeapGraphModule.
+ RegisterForField(TracePacket::kDeobfuscationMappingFieldNumber, context);
+ RegisterForField(TracePacket::kSmapsPacketFieldNumber, context);
}
ProfileModule::~ProfileModule() = default;
@@ -76,6 +87,27 @@
ParsePerfSample(ttp.timestamp, ttp.packet_data.sequence_state.get(),
decoder);
return;
+ case TracePacket::kProfilePacketFieldNumber:
+ PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
+ ParseProfilePacket(ttp.timestamp, ttp.packet_data.sequence_state.get(),
+ decoder.trusted_packet_sequence_id(),
+ decoder.profile_packet());
+ return;
+ case TracePacket::kModuleSymbolsFieldNumber:
+ PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
+ ParseModuleSymbols(decoder.module_symbols());
+ return;
+ case TracePacket::kDeobfuscationMappingFieldNumber:
+ PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
+ ParseDeobfuscationMapping(ttp.timestamp,
+ ttp.packet_data.sequence_state.get(),
+ decoder.trusted_packet_sequence_id(),
+ decoder.deobfuscation_mapping());
+ return;
+ case TracePacket::kSmapsPacketFieldNumber:
+ PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
+ ParseSmapsPacket(ttp.timestamp, decoder.smaps_packet());
+ return;
}
}
@@ -250,5 +282,287 @@
context_->storage->mutable_perf_sample_table()->Insert(sample_row);
}
+void ProfileModule::ParseProfilePacket(
+ int64_t ts,
+ PacketSequenceStateGeneration* sequence_state,
+ uint32_t seq_id,
+ ConstBytes blob) {
+ protos::pbzero::ProfilePacket::Decoder packet(blob.data, blob.size);
+ context_->heap_profile_tracker->SetProfilePacketIndex(seq_id, packet.index());
+
+ for (auto it = packet.strings(); it; ++it) {
+ protos::pbzero::InternedString::Decoder entry(*it);
+
+ const char* str = reinterpret_cast<const char*>(entry.str().data);
+ auto str_view = base::StringView(str, entry.str().size);
+ sequence_state->state()->sequence_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 =
+ ProfilePacketUtils::MakeSourceMapping(entry);
+ sequence_state->state()->sequence_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 =
+ ProfilePacketUtils::MakeSourceFrame(entry);
+ sequence_state->state()->sequence_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 =
+ ProfilePacketUtils::MakeSourceCallstack(entry);
+ sequence_state->state()->sequence_stack_profile_tracker().AddCallstack(
+ entry.iid(), src_callstack);
+ }
+
+ for (auto it = packet.process_dumps(); it; ++it) {
+ protos::pbzero::ProfilePacket::ProcessHeapSamples::Decoder entry(*it);
+
+ auto maybe_timestamp = context_->clock_tracker->ToTraceTime(
+ protos::pbzero::BUILTIN_CLOCK_MONOTONIC_COARSE,
+ static_cast<int64_t>(entry.timestamp()));
+
+ // ToTraceTime() increments the clock_sync_failure error stat in this case.
+ if (!maybe_timestamp)
+ continue;
+
+ 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(
+ stats::heapprofd_client_disconnected, pid);
+ 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) {
+ 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()) {
+ 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();
+ }
+
+ context_->heap_profile_tracker->StoreAllocation(seq_id, src_allocation);
+ }
+ }
+ if (!packet.continued()) {
+ PERFETTO_CHECK(sequence_state);
+ ProfilePacketInternLookup intern_lookup(sequence_state);
+ context_->heap_profile_tracker->FinalizeProfile(
+ seq_id, &sequence_state->state()->sequence_stack_profile_tracker(),
+ &intern_lookup);
+ }
+}
+
+void ProfileModule::ParseModuleSymbols(ConstBytes blob) {
+ protos::pbzero::ModuleSymbols::Decoder module_symbols(blob.data, blob.size);
+ StringId build_id;
+ // TODO(b/148109467): Remove workaround once all active Chrome versions
+ // write raw bytes instead of a string as build_id.
+ if (module_symbols.build_id().size == 33) {
+ build_id = context_->storage->InternString(module_symbols.build_id());
+ } else {
+ build_id = context_->storage->InternString(base::StringView(base::ToHex(
+ module_symbols.build_id().data, module_symbols.build_id().size)));
+ }
+
+ auto mapping_ids = context_->global_stack_profile_tracker->FindMappingRow(
+ context_->storage->InternString(module_symbols.path()), build_id);
+ if (mapping_ids.empty()) {
+ context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
+ return;
+ }
+ for (auto addr_it = module_symbols.address_symbols(); addr_it; ++addr_it) {
+ protos::pbzero::AddressSymbols::Decoder address_symbols(*addr_it);
+
+ uint32_t symbol_set_id = context_->storage->symbol_table().row_count();
+
+ bool has_lines = false;
+ for (auto line_it = address_symbols.lines(); line_it; ++line_it) {
+ protos::pbzero::Line::Decoder line(*line_it);
+ context_->storage->mutable_symbol_table()->Insert(
+ {symbol_set_id, context_->storage->InternString(line.function_name()),
+ context_->storage->InternString(line.source_file_name()),
+ line.line_number()});
+ has_lines = true;
+ }
+ if (!has_lines) {
+ continue;
+ }
+ 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());
+
+ for (const FrameId frame_id : frame_ids) {
+ auto* frames = context_->storage->mutable_stack_profile_frame_table();
+ uint32_t frame_row = *frames->id().IndexOf(frame_id);
+ frames->mutable_symbol_set_id()->Set(frame_row, symbol_set_id);
+ frame_found = true;
+ }
+ }
+
+ if (!frame_found) {
+ context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
+ continue;
+ }
+ }
+}
+
+void ProfileModule::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)
+ 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)
+ 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);
+
+ 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());
+ }
+ }
+
+ 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)));
+ }
+ }
+ }
+}
+
+void ProfileModule::ParseSmapsPacket(int64_t ts, ConstBytes blob) {
+ protos::pbzero::SmapsPacket::Decoder sp(blob.data, blob.size);
+ auto upid = context_->process_tracker->GetOrCreateProcess(sp.pid());
+
+ for (auto it = sp.entries(); it; ++it) {
+ protos::pbzero::SmapsEntry::Decoder e(*it);
+ context_->storage->mutable_profiler_smaps_table()->Insert(
+ {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())});
+ }
+}
+
} // 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..92f3384 100644
--- a/src/trace_processor/importers/proto/profile_module.h
+++ b/src/trace_processor/importers/proto/profile_module.h
@@ -45,6 +45,7 @@
uint32_t field_id) override;
private:
+ // chrome stack sampling:
ModuleResult TokenizeStreamingProfilePacket(
PacketSequenceState*,
TraceBlobView* packet,
@@ -54,10 +55,23 @@
PacketSequenceStateGeneration*,
protozero::ConstBytes streaming_profile_packet);
+ // perf event profiling:
void ParsePerfSample(int64_t ts,
PacketSequenceStateGeneration* sequence_state,
const protos::pbzero::TracePacket::Decoder& decoder);
+ // heap profiling:
+ void ParseProfilePacket(int64_t ts,
+ PacketSequenceStateGeneration*,
+ uint32_t seq_id,
+ protozero::ConstBytes);
+ void ParseDeobfuscationMapping(int64_t ts,
+ PacketSequenceStateGeneration*,
+ uint32_t seq_id,
+ protozero::ConstBytes);
+ void ParseModuleSymbols(protozero::ConstBytes);
+ void ParseSmapsPacket(int64_t ts, protozero::ConstBytes);
+
TraceProcessorContext* context_;
};
diff --git a/src/trace_processor/importers/proto/profiler_util.cc b/src/trace_processor/importers/proto/profiler_util.cc
index c28f2fc..277da09 100644
--- a/src/trace_processor/importers/proto/profiler_util.cc
+++ b/src/trace_processor/importers/proto/profiler_util.cc
@@ -99,6 +99,16 @@
return "com.google.android.as";
}
+ if (location.find("DeviceIntelligenceNetworkPrebuilt") !=
+ base::StringView::npos) {
+ return "com.google.android.as.oss";
+ }
+
+ if (location.find("SettingsIntelligenceGooglePrebuilt") !=
+ base::StringView::npos) {
+ return "com.google.android.settings.intelligence";
+ }
+
base::StringView gm("/product/app/PrebuiltGmail/PrebuiltGmail.apk");
if (location.size() >= gm.size() && location.substr(0, gm.size()) == gm) {
return "com.google.android.gm";
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index 26383f2..f212645 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -16,14 +16,13 @@
#include "src/trace_processor/importers/proto/proto_trace_parser.h"
-#include <inttypes.h>
#include <string.h>
+#include <cinttypes>
#include <string>
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/metatrace_events.h"
-#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/string_writer.h"
#include "perfetto/ext/base/utils.h"
@@ -38,15 +37,10 @@
#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/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"
@@ -59,10 +53,6 @@
#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/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"
@@ -111,16 +101,8 @@
void ProtoTraceParser::ParseTracePacketImpl(
int64_t ts,
const TimestampedTracePiece& ttp,
- PacketSequenceStateGeneration* sequence_state,
+ PacketSequenceStateGeneration* /*sequence_state*/,
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.
@@ -143,11 +125,6 @@
if (packet.has_trace_stats())
ParseTraceStats(packet.trace_stats());
- if (packet.has_profile_packet()) {
- ParseProfilePacket(ts, sequence_state, packet.trusted_packet_sequence_id(),
- packet.profile_packet());
- }
-
if (packet.has_perfetto_metatrace()) {
ParseMetatraceEvent(ts, packet.perfetto_metatrace());
}
@@ -155,14 +132,6 @@
if (packet.has_trace_config()) {
ParseTraceConfig(packet.trace_config());
}
-
- if (packet.has_module_symbols()) {
- ParseModuleSymbols(packet.module_symbols());
- }
-
- if (packet.has_smaps_packet()) {
- ParseSmapsPacket(ts, packet.smaps_packet());
- }
}
void ProtoTraceParser::ParseFtracePacket(uint32_t cpu,
@@ -242,207 +211,6 @@
}
}
-void ProtoTraceParser::ParseProfilePacket(
- int64_t ts,
- PacketSequenceStateGeneration* sequence_state,
- uint32_t seq_id,
- ConstBytes blob) {
- protos::pbzero::ProfilePacket::Decoder packet(blob.data, blob.size);
- context_->heap_profile_tracker->SetProfilePacketIndex(seq_id, packet.index());
-
- for (auto it = packet.strings(); it; ++it) {
- protos::pbzero::InternedString::Decoder entry(*it);
-
- const char* str = reinterpret_cast<const char*>(entry.str().data);
- auto str_view = base::StringView(str, entry.str().size);
- sequence_state->state()->sequence_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 =
- ProfilePacketUtils::MakeSourceMapping(entry);
- sequence_state->state()->sequence_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 =
- ProfilePacketUtils::MakeSourceFrame(entry);
- sequence_state->state()->sequence_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 =
- ProfilePacketUtils::MakeSourceCallstack(entry);
- sequence_state->state()->sequence_stack_profile_tracker().AddCallstack(
- entry.iid(), src_callstack);
- }
-
- for (auto it = packet.process_dumps(); it; ++it) {
- protos::pbzero::ProfilePacket::ProcessHeapSamples::Decoder entry(*it);
-
- auto maybe_timestamp = context_->clock_tracker->ToTraceTime(
- protos::pbzero::BUILTIN_CLOCK_MONOTONIC_COARSE,
- static_cast<int64_t>(entry.timestamp()));
-
- // ToTraceTime() increments the clock_sync_failure error stat in this case.
- if (!maybe_timestamp)
- continue;
-
- 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(
- stats::heapprofd_client_disconnected, pid);
- 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) {
- 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()) {
- 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();
- }
-
- context_->heap_profile_tracker->StoreAllocation(seq_id, src_allocation);
- }
- }
- if (!packet.continued()) {
- PERFETTO_CHECK(sequence_state);
- ProfilePacketInternLookup intern_lookup(sequence_state);
- context_->heap_profile_tracker->FinalizeProfile(
- seq_id, &sequence_state->state()->sequence_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)
- 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)
- 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);
-
- 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());
- }
- }
-
- 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)));
- }
- }
- }
-}
-
void ProtoTraceParser::ParseChromeEvents(int64_t ts, ConstBytes blob) {
TraceStorage* storage = context_->storage.get();
protos::pbzero::ChromeEventBundle::Decoder bundle(blob.data, blob.size);
@@ -649,6 +417,7 @@
StringId id = context_->storage->InternString(base::StringView(str));
context_->metadata_tracker->SetMetadata(metadata::trace_uuid,
Variadic::String(id));
+ context_->uuid_found_in_trace = true;
}
if (trace_config.has_unique_session_name()) {
@@ -670,86 +439,5 @@
Variadic::String(id));
}
-void ProtoTraceParser::ParseModuleSymbols(ConstBytes blob) {
- protos::pbzero::ModuleSymbols::Decoder module_symbols(blob.data, blob.size);
- StringId build_id;
- // TODO(b/148109467): Remove workaround once all active Chrome versions
- // write raw bytes instead of a string as build_id.
- if (module_symbols.build_id().size == 33) {
- build_id = context_->storage->InternString(module_symbols.build_id());
- } else {
- build_id = context_->storage->InternString(base::StringView(base::ToHex(
- module_symbols.build_id().data, module_symbols.build_id().size)));
- }
-
- auto mapping_ids = context_->global_stack_profile_tracker->FindMappingRow(
- context_->storage->InternString(module_symbols.path()), build_id);
- if (mapping_ids.empty()) {
- context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
- return;
- }
- for (auto addr_it = module_symbols.address_symbols(); addr_it; ++addr_it) {
- protos::pbzero::AddressSymbols::Decoder address_symbols(*addr_it);
-
- uint32_t symbol_set_id = context_->storage->symbol_table().row_count();
-
- bool has_lines = false;
- for (auto line_it = address_symbols.lines(); line_it; ++line_it) {
- protos::pbzero::Line::Decoder line(*line_it);
- context_->storage->mutable_symbol_table()->Insert(
- {symbol_set_id, context_->storage->InternString(line.function_name()),
- context_->storage->InternString(line.source_file_name()),
- line.line_number()});
- has_lines = true;
- }
- if (!has_lines) {
- continue;
- }
- 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());
-
- for (const FrameId frame_id : frame_ids) {
- auto* frames = context_->storage->mutable_stack_profile_frame_table();
- uint32_t frame_row = *frames->id().IndexOf(frame_id);
- frames->mutable_symbol_set_id()->Set(frame_row, symbol_set_id);
- frame_found = true;
- }
- }
-
- if (!frame_found) {
- context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
- continue;
- }
- }
-}
-
-void ProtoTraceParser::ParseSmapsPacket(int64_t ts, ConstBytes blob) {
- protos::pbzero::SmapsPacket::Decoder sp(blob.data, blob.size);
- auto upid = context_->process_tracker->GetOrCreateProcess(sp.pid());
-
- for (auto it = sp.entries(); it; ++it) {
- protos::pbzero::SmapsEntry::Decoder e(*it);
- context_->storage->mutable_profiler_smaps_table()->Insert(
- {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())});
- }
-}
-
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.h b/src/trace_processor/importers/proto/proto_trace_parser.h
index f33bc5f..48ec82e 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.h
+++ b/src/trace_processor/importers/proto/proto_trace_parser.h
@@ -40,7 +40,6 @@
namespace trace_processor {
-class ArgsTracker;
class PacketSequenceState;
class TraceProcessorContext;
@@ -62,19 +61,9 @@
const protos::pbzero::TracePacket_Decoder&);
void ParseTraceStats(ConstBytes);
- void ParseProfilePacket(int64_t ts,
- PacketSequenceStateGeneration*,
- uint32_t seq_id,
- ConstBytes);
- void ParseDeobfuscationMapping(int64_t ts,
- PacketSequenceStateGeneration*,
- uint32_t seq_id,
- ConstBytes);
void ParseChromeEvents(int64_t ts, ConstBytes);
void ParseMetatraceEvent(int64_t ts, ConstBytes);
void ParseTraceConfig(ConstBytes);
- void ParseModuleSymbols(ConstBytes);
- void ParseSmapsPacket(int64_t ts, ConstBytes);
private:
TraceProcessorContext* context_;
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..60c1606 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
@@ -252,7 +252,8 @@
context_.flow_tracker.reset(flow_);
clock_ = new ClockTracker(&context_);
context_.clock_tracker.reset(clock_);
- context_.sorter.reset(new TraceSorter(CreateParser(), 0 /*window size*/));
+ context_.sorter.reset(new TraceSorter(&context_, CreateParser(),
+ TraceSorter::SortingMode::kFullSort));
context_.descriptor_pool_.reset(new DescriptorPool());
RegisterDefaultModules(&context_);
@@ -333,6 +334,7 @@
PushSchedSwitch(10, 1000, 10, base::StringView(kProc2Name), 256,
32, 100, base::StringView(kProc1Name), 1024));
Tokenize();
+ context_.sorter->ExtractEventsForced();
}
TEST_F(ProtoTraceParserTest, LoadEventsIntoRaw) {
@@ -364,6 +366,7 @@
EXPECT_CALL(*process_, GetOrCreateProcess(123));
Tokenize();
+ context_.sorter->ExtractEventsForced();
const auto& raw = context_.storage->raw_table();
ASSERT_EQ(raw.row_count(), 2u);
@@ -414,6 +417,7 @@
field->set_uint_value(3);
Tokenize();
+ context_.sorter->ExtractEventsForced();
const auto& raw = storage_->raw_table();
@@ -481,6 +485,7 @@
32, 10, base::StringView(kProcName2), 512));
Tokenize();
+ context_.sorter->ExtractEventsForced();
}
TEST_F(ProtoTraceParserTest, LoadMultiplePackets) {
@@ -526,6 +531,7 @@
PushSchedSwitch(10, 1001, 100, base::StringView(kProcName1), 256,
32, 10, base::StringView(kProcName2), 512));
Tokenize();
+ context_.sorter->ExtractEventsForced();
}
TEST_F(ProtoTraceParserTest, RepeatedLoadSinglePacket) {
@@ -548,6 +554,7 @@
PushSchedSwitch(10, 1000, 10, base::StringView(kProcName2), 256,
32, 100, base::StringView(kProcName1), 1024));
Tokenize();
+ context_.sorter->ExtractEventsForced();
bundle = trace_->add_packet()->set_ftrace_events();
bundle->set_cpu(10);
@@ -567,6 +574,7 @@
PushSchedSwitch(10, 1001, 100, base::StringView(kProcName1), 256,
32, 10, base::StringView(kProcName2), 512));
Tokenize();
+ context_.sorter->ExtractEventsForced();
}
TEST_F(ProtoTraceParserTest, LoadCpuFreq) {
@@ -581,6 +589,7 @@
EXPECT_CALL(*event_, PushCounter(1000, DoubleEq(2000), TrackId{0}));
Tokenize();
+ context_.sorter->ExtractEventsForced();
EXPECT_EQ(context_.storage->cpu_counter_track_table().cpu()[0], 10u);
}
@@ -598,6 +607,7 @@
EXPECT_CALL(*event_, PushCounter(static_cast<int64_t>(ts),
DoubleEq(value * 1024.0), TrackId{0u}));
Tokenize();
+ context_.sorter->ExtractEventsForced();
EXPECT_EQ(context_.storage->track_table().row_count(), 1u);
}
@@ -615,6 +625,7 @@
EXPECT_CALL(*event_, PushCounter(static_cast<int64_t>(ts), DoubleEq(value),
TrackId{0u}));
Tokenize();
+ context_.sorter->ExtractEventsForced();
EXPECT_EQ(context_.storage->track_table().row_count(), 1u);
}
@@ -632,6 +643,7 @@
SetProcessMetadata(1, Eq(3u), base::StringView(kProcName1),
base::StringView(kProcName1)));
Tokenize();
+ context_.sorter->ExtractEventsForced();
}
TEST_F(ProtoTraceParserTest, LoadProcessPacket_FirstCmdline) {
@@ -649,6 +661,7 @@
SetProcessMetadata(1, Eq(3u), base::StringView(kProcName1),
base::StringView("proc1 proc2")));
Tokenize();
+ context_.sorter->ExtractEventsForced();
}
TEST_F(ProtoTraceParserTest, LoadThreadPacket) {
@@ -659,11 +672,10 @@
EXPECT_CALL(*process_, UpdateThread(1, 2));
Tokenize();
+ context_.sorter->ExtractEventsForced();
}
TEST_F(ProtoTraceParserTest, ProcessNameFromProcessDescriptor) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -707,8 +719,6 @@
}
TEST_F(ProtoTraceParserTest, ThreadNameFromThreadDescriptor) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -763,9 +773,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventWithoutInternedData) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -815,8 +822,7 @@
Tokenize();
- EXPECT_CALL(*process_, UpdateThread(16, 15))
- .WillRepeatedly(Return(1));
+ EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
tables::ThreadTable::Row row(16);
row.upid = 1u;
@@ -860,9 +866,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventWithoutInternedDataWithTypes) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -909,8 +912,7 @@
Tokenize();
- EXPECT_CALL(*process_, UpdateThread(16, 15))
- .WillRepeatedly(Return(1));
+ EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
tables::ThreadTable::Row row(16);
row.upid = 1u;
@@ -953,9 +955,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventWithInternedData) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -1087,8 +1086,7 @@
Tokenize();
- EXPECT_CALL(*process_, UpdateThread(16, 15))
- .WillRepeatedly(Return(1));
+ EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
tables::ThreadTable::Row row(16);
row.upid = 2u;
@@ -1178,9 +1176,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventAsyncEvents) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -1334,9 +1329,6 @@
// TODO(eseckler): Also test instant events on separate tracks.
TEST_F(ProtoTraceParserTest, TrackEventWithTrackDescriptors) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
// Sequence 1.
{
auto* packet = trace_->add_packet();
@@ -1540,9 +1532,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventWithResortedCounterDescriptor) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
// Descriptors with timestamps after the event below. They will be tokenized
// in the order they appear here, but then resorted before parsing to appear
// after the events below.
@@ -1643,9 +1632,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventWithoutIncrementalStateReset) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -1704,9 +1690,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventWithoutThreadDescriptor) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
// Event should be discarded because it specifies delta timestamps and no
// thread descriptor was seen yet.
@@ -1746,9 +1729,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventWithDataLoss) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -1762,7 +1742,7 @@
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
auto* event = packet->set_track_event();
- event->set_timestamp_delta_us(10); // absolute: 1010.
+ event->set_timestamp_delta_us(10); // absolute: 1010.
event->add_category_iids(1);
auto* legacy_event = event->set_legacy_event();
legacy_event->set_name_iid(1);
@@ -1815,7 +1795,7 @@
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
auto* event = packet->set_track_event();
- event->set_timestamp_delta_us(10); // absolute: 2010.
+ event->set_timestamp_delta_us(10); // absolute: 2010.
event->add_category_iids(1);
auto* legacy_event = event->set_legacy_event();
legacy_event->set_name_iid(1);
@@ -1840,9 +1820,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventMultipleSequences) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -1856,7 +1833,7 @@
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
auto* event = packet->set_track_event();
- event->set_timestamp_delta_us(10); // absolute: 1010.
+ event->set_timestamp_delta_us(10); // absolute: 1010.
event->add_category_iids(1);
auto* legacy_event = event->set_legacy_event();
legacy_event->set_name_iid(1);
@@ -1883,7 +1860,7 @@
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(2);
auto* event = packet->set_track_event();
- event->set_timestamp_delta_us(10); // absolute: 1005.
+ event->set_timestamp_delta_us(10); // absolute: 1005.
event->add_category_iids(1);
auto* legacy_event = event->set_legacy_event();
legacy_event->set_name_iid(1);
@@ -1901,7 +1878,7 @@
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
auto* event = packet->set_track_event();
- event->set_timestamp_delta_us(10); // absolute: 1020.
+ event->set_timestamp_delta_us(10); // absolute: 1020.
event->add_category_iids(1);
auto* legacy_event = event->set_legacy_event();
legacy_event->set_name_iid(1);
@@ -1911,7 +1888,7 @@
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(2);
auto* event = packet->set_track_event();
- event->set_timestamp_delta_us(10); // absolute: 1015.
+ event->set_timestamp_delta_us(10); // absolute: 1015.
event->add_category_iids(1);
auto* legacy_event = event->set_legacy_event();
legacy_event->set_name_iid(1);
@@ -1920,10 +1897,8 @@
Tokenize();
- EXPECT_CALL(*process_, UpdateThread(16, 15))
- .WillRepeatedly(Return(1));
- EXPECT_CALL(*process_, UpdateThread(17, 15))
- .WillRepeatedly(Return(2));
+ EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
+ EXPECT_CALL(*process_, UpdateThread(17, 15)).WillRepeatedly(Return(2));
tables::ThreadTable::Row t1(16);
t1.upid = 1u;
@@ -1950,8 +1925,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventWithDebugAnnotations) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
MockBoundInserter inserter;
{
@@ -1967,7 +1940,7 @@
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
auto* event = packet->set_track_event();
- event->set_timestamp_delta_us(10); // absolute: 1010.
+ event->set_timestamp_delta_us(10); // absolute: 1010.
event->add_category_iids(1);
auto* annotation1 = event->add_debug_annotations();
annotation1->set_name_iid(1);
@@ -2019,7 +1992,7 @@
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
auto* event = packet->set_track_event();
- event->set_timestamp_delta_us(10); // absolute: 1020.
+ event->set_timestamp_delta_us(10); // absolute: 1020.
event->add_category_iids(1);
auto* annotation3 = event->add_debug_annotations();
annotation3->set_name_iid(3);
@@ -2153,9 +2126,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventWithTaskExecution) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -2169,7 +2139,7 @@
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
auto* event = packet->set_track_event();
- event->set_timestamp_delta_us(10); // absolute: 1010.
+ event->set_timestamp_delta_us(10); // absolute: 1010.
event->add_category_iids(1);
auto* task_execution = event->set_task_execution();
task_execution->set_posted_from_iid(1);
@@ -2218,9 +2188,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventWithLogMessage) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -2234,7 +2201,7 @@
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
auto* event = packet->set_track_event();
- event->set_timestamp_delta_us(10); // absolute: 1010.
+ event->set_timestamp_delta_us(10); // absolute: 1010.
event->add_category_iids(1);
auto* log_message = event->set_log_message();
@@ -2294,9 +2261,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventParseLegacyEventIntoRawTable) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -2398,9 +2362,6 @@
}
TEST_F(ProtoTraceParserTest, TrackEventLegacyTimestampsWithClockSnapshot) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
clock_->AddSnapshot({{protos::pbzero::BUILTIN_CLOCK_BOOTTIME, 0},
{protos::pbzero::BUILTIN_CLOCK_MONOTONIC, 1000000}});
@@ -2442,9 +2403,6 @@
}
TEST_F(ProtoTraceParserTest, ParseEventWithClockIdButWithoutClockSnapshot) {
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_timestamp(1000);
@@ -2471,9 +2429,6 @@
static const char kIntName[] = "int_name";
static const int kIntValue = 123;
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_timestamp(1000);
@@ -2511,9 +2466,6 @@
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);
@@ -2558,9 +2510,6 @@
static const char kDataPart1[] = "bbb";
static const char kFullData[] = "aaabbb";
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -2588,9 +2537,6 @@
TEST_F(ProtoTraceParserTest, ParseChromeLegacyJsonIntoRawTable) {
static const char kUserTraceEvent[] = "{\"user\":1}";
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
{
auto* packet = trace_->add_packet();
packet->set_trusted_packet_sequence_id(1);
@@ -2622,9 +2568,6 @@
static const char kTag1[] = "tag1";
static const char kTag2[] = "tag2";
- context_.sorter.reset(new TraceSorter(
- CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
auto* metadata = trace_->add_packet()->set_chrome_benchmark_metadata();
metadata->set_benchmark_name(kName);
metadata->add_story_tags(kTag1);
@@ -2653,9 +2596,6 @@
}
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();
@@ -2723,6 +2663,7 @@
}
Tokenize();
+ context_.sorter->ExtractEventsForced();
// Packet-level errors reflected in stats storage.
const auto& stats = context_.storage->stats();
@@ -2775,6 +2716,7 @@
}
Tokenize();
+ context_.sorter->ExtractEventsForced();
// Packet-level errors reflected in stats storage.
const auto& stats = context_.storage->stats();
@@ -2860,10 +2802,10 @@
samples->set_process_priority(30);
}
- EXPECT_CALL(*process_, UpdateThread(16, 15))
- .WillRepeatedly(Return(1));
+ EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
Tokenize();
+ context_.sorter->ExtractEventsForced();
// Verify cpu_profile_samples.
const auto& samples = storage_->cpu_profile_stack_sample_table();
@@ -2950,6 +2892,7 @@
EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
Tokenize();
+ context_.sorter->ExtractEventsForced();
const auto& samples = storage_->cpu_profile_stack_sample_table();
EXPECT_EQ(samples.row_count(), 1u);
@@ -2966,10 +2909,12 @@
config->set_trace_uuid_msb(2);
ASSERT_TRUE(Tokenize().ok());
+ context_.sorter->ExtractEventsForced();
SqlValue value =
context_.metadata_tracker->GetMetadataForTesting(metadata::trace_uuid);
EXPECT_STREQ(value.string_value, "00000000-0000-0002-0000-000000000001");
+ ASSERT_TRUE(context_.uuid_found_in_trace);
}
TEST_F(ProtoTraceParserTest, ConfigPbtxt) {
@@ -2977,6 +2922,7 @@
config->add_buffers()->set_size_kb(42);
ASSERT_TRUE(Tokenize().ok());
+ context_.sorter->ExtractEventsForced();
SqlValue value = context_.metadata_tracker->GetMetadataForTesting(
metadata::trace_config_pbtxt);
diff --git a/src/trace_processor/importers/proto/proto_trace_reader.cc b/src/trace_processor/importers/proto/proto_trace_reader.cc
index be5f1ff..e8ca900 100644
--- a/src/trace_processor/importers/proto/proto_trace_reader.cc
+++ b/src/trace_processor/importers/proto/proto_trace_reader.cc
@@ -69,6 +69,7 @@
auto extension = decoder.extension_set();
return context_->descriptor_pool_->AddFromFileDescriptorSet(
extension.data, extension.size,
+ /*skip_prefixes*/ {},
/*merge_existing_messages=*/true);
}
@@ -232,49 +233,12 @@
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);
+ if (trace_config.write_into_file() && !trace_config.flush_period_ms()) {
+ PERFETTO_ELOG(
+ "It is strongly recommended to have flush_period_ms set when "
+ "write_into_file is turned on. This trace will be loaded fully "
+ "into memory before sorting which increases the likliehoold of "
+ "OOMs.");
}
}
@@ -447,6 +411,12 @@
context_->metadata_tracker->SetMetadata(
metadata::all_data_source_started_ns, Variadic::Integer(ts));
}
+ if (tse.all_data_sources_flushed()) {
+ context_->sorter->NotifyFlushEvent();
+ }
+ if (tse.read_tracing_buffers_completed()) {
+ context_->sorter->NotifyReadBufferEvent();
+ }
return util::OkStatus();
}
diff --git a/src/trace_processor/importers/proto/track_event_tracker.cc b/src/trace_processor/importers/proto/track_event_tracker.cc
index bed158a..c4cbd05 100644
--- a/src/trace_processor/importers/proto/track_event_tracker.cc
+++ b/src/trace_processor/importers/proto/track_event_tracker.cc
@@ -392,7 +392,8 @@
reservation.min_timestamp);
upid = context_->process_tracker->StartNewProcess(
- base::nullopt, base::nullopt, *reservation.pid, kNullStringId);
+ base::nullopt, base::nullopt, *reservation.pid, kNullStringId,
+ ThreadNamePriority::kTrackDescriptor);
descriptor_uuids_by_upid_[upid] = uuid;
}
diff --git a/src/trace_processor/importers/syscalls/syscall_tracker.cc b/src/trace_processor/importers/syscalls/syscall_tracker.cc
index 129502d..a60be09 100644
--- a/src/trace_processor/importers/syscalls/syscall_tracker.cc
+++ b/src/trace_processor/importers/syscalls/syscall_tracker.cc
@@ -16,11 +16,10 @@
#include "src/trace_processor/importers/syscalls/syscall_tracker.h"
+#include <cinttypes>
#include <type_traits>
#include <utility>
-#include <inttypes.h>
-
#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/importers/syscalls/syscalls_aarch32.h"
diff --git a/src/trace_processor/importers/systrace/systrace_line.h b/src/trace_processor/importers/systrace/systrace_line.h
index 817672b..80ce931 100644
--- a/src/trace_processor/importers/systrace/systrace_line.h
+++ b/src/trace_processor/importers/systrace/systrace_line.h
@@ -17,7 +17,7 @@
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_SYSTRACE_SYSTRACE_LINE_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_SYSTRACE_SYSTRACE_LINE_H_
-#include <inttypes.h>
+#include <cinttypes>
#include <string>
namespace perfetto {
diff --git a/src/trace_processor/importers/systrace/systrace_line_parser.cc b/src/trace_processor/importers/systrace/systrace_line_parser.cc
index d412458..15f6827 100644
--- a/src/trace_processor/importers/systrace/systrace_line_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_line_parser.cc
@@ -28,8 +28,8 @@
#include "src/trace_processor/importers/systrace/systrace_parser.h"
#include "src/trace_processor/types/task_state.h"
-#include <inttypes.h>
#include <cctype>
+#include <cinttypes>
#include <string>
#include <unordered_map>
diff --git a/src/trace_processor/importers/systrace/systrace_parser.cc b/src/trace_processor/importers/systrace/systrace_parser.cc
index b9655d4..1eca41c 100644
--- a/src/trace_processor/importers/systrace/systrace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_parser.cc
@@ -17,6 +17,7 @@
#include "src/trace_processor/importers/systrace/systrace_parser.h"
#include "perfetto/ext/base/optional.h"
+#include "perfetto/ext/base/string_utils.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"
@@ -29,6 +30,7 @@
SystraceParser::SystraceParser(TraceProcessorContext* ctx)
: context_(ctx),
lmk_id_(ctx->storage->InternString("mem.lmk")),
+ oom_score_adj_id_(ctx->storage->InternString("oom_score_adj")),
screen_state_id_(ctx->storage->InternString("ScreenState")),
cookie_id_(ctx->storage->InternString("cookie")) {}
@@ -139,6 +141,7 @@
TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
context_->slice_tracker->Begin(ts, track_id, kNullStringId /* cat */,
name_id);
+ PostProcessSpecialSliceBegin(ts, point.name);
break;
}
@@ -250,5 +253,34 @@
}
}
+void SystraceParser::PostProcessSpecialSliceBegin(int64_t ts,
+ base::StringView name) {
+ if (name.StartsWith("lmk,")) {
+ // LMK events introduced with http://aosp/1782391 are treated specially
+ // to parse the killed process oom_score_adj out of them.
+ // Format is 'lmk,pid,reason,oom adj,...'
+ std::vector<std::string> toks = base::SplitString(name.ToStdString(), ",");
+ if (toks.size() < 4) {
+ return;
+ }
+ auto killed_pid = base::StringToUInt32(toks[1]);
+ auto oom_score_adj = base::StringToInt32(toks[3]);
+ if (!killed_pid || !oom_score_adj) {
+ return;
+ }
+
+ UniquePid killed_upid =
+ context_->process_tracker->GetOrCreateProcess(*killed_pid);
+ // Add the oom score entry
+ TrackId track = context_->track_tracker->InternProcessCounterTrack(
+ oom_score_adj_id_, killed_upid);
+ context_->event_tracker->PushCounter(ts, *oom_score_adj, track);
+
+ // Add mem.lmk instant event for consistency with other methods.
+ context_->event_tracker->PushInstant(ts, lmk_id_, killed_upid,
+ RefType::kRefUpid);
+ }
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/systrace/systrace_parser.h b/src/trace_processor/importers/systrace/systrace_parser.h
index a369af9..df7b92f 100644
--- a/src/trace_processor/importers/systrace/systrace_parser.h
+++ b/src/trace_processor/importers/systrace/systrace_parser.h
@@ -227,9 +227,11 @@
void ParseSystracePoint(int64_t ts,
uint32_t pid,
systrace_utils::SystraceTracePoint event);
+ void PostProcessSpecialSliceBegin(int64_t ts, base::StringView name);
TraceProcessorContext* const context_;
const StringId lmk_id_;
+ const StringId oom_score_adj_id_;
const StringId screen_state_id_;
const StringId cookie_id_;
};
diff --git a/src/trace_processor/importers/systrace/systrace_trace_parser.cc b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
index d333af3..2b797db 100644
--- a/src/trace_processor/importers/systrace/systrace_trace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
@@ -22,8 +22,8 @@
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/trace_sorter.h"
-#include <inttypes.h>
#include <cctype>
+#include <cinttypes>
#include <string>
#include <unordered_map>
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index 00a1e4e..8311cde 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -43,6 +43,7 @@
"android/android_package_list.sql",
"android/android_task_names.sql",
"android/android_thread_time_in_state.sql",
+ "android/android_trace_quality.sql",
"android/cpu_info.sql",
"android/display_metrics.sql",
"android/g2d.sql",
@@ -58,11 +59,17 @@
"android/process_mem.sql",
"android/process_metadata.sql",
"android/process_oom_score.sql",
+ "android/profiler_smaps.sql",
"android/mem_stats_priority_breakdown.sql",
+ "android/android_multiuser.sql",
+ "android/android_multiuser_populator.sql",
"android/span_view_stats.sql",
"android/android_sysui_cuj.sql",
+ "android/android_sysui_cuj_jank_query.sql",
"android/process_counter_span_view.sql",
"android/global_counter_span_view.sql",
+ "android/gpu_counter_span_view.sql",
+ "android/thread_counter_span_view.sql",
"android/unsymbolized_frames.sql",
"chrome/actual_power_by_category.sql",
"chrome/actual_power_by_rail_mode.sql",
@@ -73,6 +80,9 @@
"chrome/cpu_time_by_rail_mode.sql",
"chrome/estimated_power_by_category.sql",
"chrome/estimated_power_by_rail_mode.sql",
+ "chrome/gesture_jank.sql",
+ "chrome/gesture_flow_event.sql",
+ "chrome/gesture_flow_event_queuing_delay.sql",
"chrome/rail_modes.sql",
"chrome/scroll_jank.sql",
"chrome/scroll_jank_cause.sql",
@@ -83,6 +93,9 @@
"chrome/scroll_flow_event.sql",
"chrome/scroll_flow_event_queuing_delay.sql",
"chrome/test_chrome_metric.sql",
+ "chrome/touch_flow_event.sql",
+ "chrome/touch_flow_event_queuing_delay.sql",
+ "chrome/touch_jank.sql",
"experimental/blink_gc_metric.sql",
"experimental/frame_times.sql",
"experimental/media_metric.sql",
diff --git a/src/trace_processor/metrics/android/android_batt.sql b/src/trace_processor/metrics/android/android_batt.sql
index db0fbf3..070a518 100644
--- a/src/trace_processor/metrics/android/android_batt.sql
+++ b/src/trace_processor/metrics/android/android_batt.sql
@@ -83,29 +83,6 @@
)
GROUP BY group_id;
--- 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
@@ -126,13 +103,18 @@
EXTRACT_ARG(arg_set_id, 'start') AS start
FROM raw
WHERE name = 'suspend_resume'
- ) JOIN device_action USING(action)
+ )
+ -- Different device kernels log different actions when suspending.
+ -- Fortunately each action only appears in the kernel in which it's
+ -- relevant so we can simply look for any of them.
+ WHERE action IN ('timekeeping_freeze', 'syscore_resume')
)
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?)
+-- TODO(simonmacm) remove this when we no longer need suspend-resume from R
+-- phones.
SELECT
ts,
dur,
@@ -202,9 +184,6 @@
)
);
-DROP TABLE device_action_mapping;
-DROP TABLE device_action;
-
SELECT RUN_METRIC('android/global_counter_span_view.sql',
'table_name', 'screen_state',
'counter_name', 'ScreenState');
diff --git a/src/trace_processor/metrics/android/android_gpu.sql b/src/trace_processor/metrics/android/android_gpu.sql
index 644f00d..f0c0456 100644
--- a/src/trace_processor/metrics/android/android_gpu.sql
+++ b/src/trace_processor/metrics/android/android_gpu.sql
@@ -56,12 +56,58 @@
) AS proto
FROM agg_proc_gpu_view;
+SELECT RUN_METRIC('android/gpu_counter_span_view.sql',
+ 'table_name', 'gpu_freq',
+ 'counter_name', 'gpufreq');
+
+DROP VIEW IF EXISTS metrics_per_freq_view;
+CREATE VIEW metrics_per_freq_view AS
+WITH
+total_dur_per_freq AS (
+ SELECT
+ gpu_id,
+ gpu_freq_val AS freq,
+ SUM(dur) AS dur_ns
+ FROM gpu_freq_span
+ GROUP BY gpu_id, gpu_freq_val
+),
+total_dur_per_gpu AS (
+ SELECT
+ gpu_id,
+ SUM(dur) AS dur_ns
+ FROM gpu_freq_span
+ GROUP BY gpu_id
+)
+SELECT
+ gpu_id,
+ AndroidGpuMetric_FrequencyMetric_MetricsPerFrequency(
+ 'freq', CAST(freq as INT64),
+ 'dur_ms', f.dur_ns / 1e6,
+ 'percentage', f.dur_ns * 100.0 / g.dur_ns
+ ) AS proto
+FROM total_dur_per_freq f LEFT JOIN total_dur_per_gpu g USING (gpu_id);
+
+DROP VIEW IF EXISTS gpu_freq_metrics_view;
+CREATE VIEW gpu_freq_metrics_view AS
+SELECT
+ AndroidGpuMetric_FrequencyMetric(
+ 'gpu_id', gpu_id,
+ 'freq_max', CAST(MAX(gpu_freq_val) as INT64),
+ 'freq_min', CAST(MIN(gpu_freq_val) as INT64),
+ 'freq_avg', SUM(gpu_freq_val * dur) / SUM(dur),
+ 'used_freqs', (SELECT RepeatedField(proto) FROM metrics_per_freq_view
+ WHERE metrics_per_freq_view.gpu_id = gpu_freq_span.gpu_id)
+ ) AS proto
+FROM gpu_freq_span
+GROUP BY gpu_id;
+
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)
+ 'mem_avg', CAST(SUM(global_gpu_memory_val * dur) / SUM(dur) as INT64),
+ 'freq_metrics', (SELECT RepeatedField(proto) FROM gpu_freq_metrics_view)
)
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
index 7c46107..b8dc0dc 100644
--- a/src/trace_processor/metrics/android/android_hwcomposer.sql
+++ b/src/trace_processor/metrics/android/android_hwcomposer.sql
@@ -48,6 +48,58 @@
'output', 'hwc_execution_spans'
);
+
+SELECT RUN_METRIC('android/thread_counter_span_view.sql',
+ 'table_name', 'dpu_vote_clock',
+ 'counter_name', 'dpu_vote_clock'
+);
+
+SELECT RUN_METRIC('android/thread_counter_span_view.sql',
+ 'table_name', 'dpu_vote_avg_bw',
+ 'counter_name', 'dpu_vote_avg_bw'
+);
+
+SELECT RUN_METRIC('android/thread_counter_span_view.sql',
+ 'table_name', 'dpu_vote_peak_bw',
+ 'counter_name', 'dpu_vote_peak_bw'
+);
+
+SELECT RUN_METRIC('android/thread_counter_span_view.sql',
+ 'table_name', 'dpu_vote_rt_bw',
+ 'counter_name', 'dpu_vote_rt_bw'
+);
+
+DROP VIEW IF EXISTS dpu_vote_thread;
+CREATE VIEW dpu_vote_thread AS
+SELECT DISTINCT s.utid, t.tid
+FROM (
+ SELECT utid FROM dpu_vote_clock_span
+ UNION
+ SELECT utid FROM dpu_vote_avg_bw_span
+ UNION
+ SELECT utid FROM dpu_vote_peak_bw_span
+) s JOIN thread t ON s.utid = t.utid;
+
+DROP VIEW IF EXISTS dpu_vote_metrics;
+CREATE VIEW dpu_vote_metrics AS
+SELECT AndroidHwcomposerMetrics_DpuVoteMetrics(
+ 'tid', tid,
+ 'avg_dpu_vote_clock',
+ (SELECT SUM(dpu_vote_clock_val * dur) / SUM(dur)
+ FROM dpu_vote_clock_span s WHERE s.utid = t.utid),
+ 'avg_dpu_vote_avg_bw',
+ (SELECT SUM(dpu_vote_avg_bw_val * dur) / SUM(dur)
+ FROM dpu_vote_avg_bw_span s WHERE s.utid = t.utid),
+ 'avg_dpu_vote_peak_bw',
+ (SELECT SUM(dpu_vote_peak_bw_val * dur) / SUM(dur)
+ FROM dpu_vote_peak_bw_span s WHERE s.utid = t.utid),
+ 'avg_dpu_vote_rt_bw',
+ (SELECT SUM(dpu_vote_rt_bw_val * dur) / SUM(dur)
+ FROM dpu_vote_rt_bw_span s WHERE s.utid = t.utid)
+) AS proto
+FROM dpu_vote_thread t
+ORDER BY tid;
+
DROP VIEW IF EXISTS android_hwcomposer_output;
CREATE VIEW android_hwcomposer_output AS
SELECT AndroidHwcomposerMetrics(
@@ -79,5 +131,6 @@
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')
+ WHERE validation_type = 'separated_validation'),
+ 'dpu_vote_metrics', (SELECT RepeatedField(proto) FROM dpu_vote_metrics)
);
diff --git a/src/trace_processor/metrics/android/android_lmk.sql b/src/trace_processor/metrics/android/android_lmk.sql
index e4f6974..8c66278 100644
--- a/src/trace_processor/metrics/android/android_lmk.sql
+++ b/src/trace_processor/metrics/android/android_lmk.sql
@@ -40,23 +40,30 @@
CREATE VIEW android_lmk_event AS
WITH raw_events AS (
SELECT
- ts,
- LEAD(ts) OVER (ORDER BY ts) - ts AS dur,
- value AS tid
- FROM counter c
- JOIN counter_track t ON t.id = c.track_id
- WHERE t.name = 'kill_one_process'
+ ts,
+ LEAD(ts) OVER (ORDER BY ts) - ts AS dur,
+ CAST(value AS INTEGER) AS pid
+ FROM counter c
+ JOIN counter_track t ON t.id = c.track_id
+ WHERE t.name = 'kill_one_process'
+ UNION ALL
+ SELECT
+ slice.ts,
+ slice.dur,
+ CAST(STR_SPLIT(slice.name, ",", 1) AS INTEGER) AS pid
+ FROM slice
+ WHERE slice.name LIKE 'lmk,%'
),
lmks_with_proc_name AS (
SELECT
*,
process.name as process_name
FROM raw_events
- LEFT JOIN thread ON
- thread.tid = raw_events.tid AND
- raw_events.ts BETWEEN thread.start_ts AND thread.end_ts
- LEFT JOIN process USING(upid)
- WHERE raw_events.tid != 0
+ LEFT JOIN process ON
+ process.pid = raw_events.pid
+ AND (raw_events.ts >= process.start_ts OR process.start_ts IS NULL)
+ AND (raw_events.ts < process.end_ts OR process.end_ts IS NULL)
+ WHERE raw_events.pid != 0
)
SELECT
'slice' as track_type,
diff --git a/src/trace_processor/metrics/android/android_multiuser.sql b/src/trace_processor/metrics/android/android_multiuser.sql
new file mode 100644
index 0000000..bb5e4fc
--- /dev/null
+++ b/src/trace_processor/metrics/android/android_multiuser.sql
@@ -0,0 +1,26 @@
+--
+-- 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_multiuser_populator.sql',
+ 'output_table_name', 'event_user_switch',
+ 'start_event', 'user_start',
+ 'end_event', 'launcher_end');
+
+DROP VIEW IF EXISTS android_multiuser_output;
+CREATE VIEW android_multiuser_output AS
+SELECT AndroidMultiuserMetric(
+ 'user_switch', (SELECT * FROM event_user_switch)
+);
diff --git a/src/trace_processor/metrics/android/android_multiuser_populator.sql b/src/trace_processor/metrics/android/android_multiuser_populator.sql
new file mode 100644
index 0000000..65dbab1
--- /dev/null
+++ b/src/trace_processor/metrics/android/android_multiuser_populator.sql
@@ -0,0 +1,117 @@
+--
+-- 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 the important timestamps for Multiuser events.
+DROP VIEW IF EXISTS multiuser_events;
+CREATE VIEW multiuser_events AS
+SELECT
+ {{start_event}}_time_ns AS event_start_time_ns,
+ {{end_event}}_time_ns AS event_end_time_ns
+FROM
+ (
+ SELECT slice.ts AS user_start_time_ns
+ FROM slice
+ WHERE (slice.name LIKE "onBeforeStartUser%")
+ -- TODO: Use a signal based on SysUi so that it covers all switching, not just starting.
+ ),
+ (
+ SELECT slice.ts + slice.dur AS launcher_end_time_ns
+ FROM slice
+ WHERE (slice.name = "launching: com.google.android.apps.nexuslauncher")
+ );
+
+-- Calculation of the duration of the Multiuser event of interest.
+DROP VIEW IF EXISTS multiuser_timing;
+CREATE VIEW multiuser_timing AS
+SELECT
+ CAST((event_end_time_ns - event_start_time_ns) / 1e6 + 0.5 AS INT) AS duration_ms
+FROM
+ multiuser_events;
+
+
+-- Calculate CPU usage during the Multiuser event of interest.
+
+-- Get all the scheduling slices.
+DROP VIEW IF EXISTS sp_sched;
+CREATE VIEW sp_sched AS
+SELECT ts, dur, cpu, utid
+FROM sched;
+-- Get all the cpu frequency slices.
+DROP VIEW IF EXISTS sp_frequency;
+CREATE VIEW sp_frequency AS
+SELECT
+ ts,
+ lead(ts) OVER (PARTITION BY track_id ORDER BY ts) - ts as dur,
+ cpu,
+ value as freq_khz
+FROM counter
+JOIN cpu_counter_track ON counter.track_id = cpu_counter_track.id;
+-- Create the span joined table which combines cpu frequency with scheduling slices.
+DROP TABLE IF EXISTS sched_with_frequency;
+CREATE VIRTUAL TABLE sched_with_frequency
+USING SPAN_JOIN(sp_sched PARTITIONED cpu, sp_frequency PARTITIONED cpu);
+
+-- Calculate the CPU cycles spent per process during the duration.
+DROP VIEW IF EXISTS cpu_usage_all;
+CREATE VIEW cpu_usage_all AS
+SELECT
+ process.uid / 100000 AS user_id,
+ process.name AS process_name,
+ SUM(dur * freq_khz) / 1e9 AS cpu_kcycles
+FROM
+ sched_with_frequency
+ JOIN thread USING (utid)
+ JOIN process USING (upid)
+WHERE
+ ts >= (SELECT event_start_time_ns FROM multiuser_events)
+ AND
+ ts <= (SELECT event_end_time_ns FROM multiuser_events)
+GROUP BY upid, process.name
+ORDER BY cpu_kcycles DESC;
+
+-- Get the data from cpu_usage_all, but also with the percentage.
+DROP VIEW IF EXISTS cpu_usage;
+CREATE VIEW cpu_usage AS
+SELECT
+ user_id,
+ process_name,
+ CAST(cpu_kcycles / 1e3 AS INT) AS cpu_mcycles,
+ cpu_kcycles / (SELECT SUM(cpu_kcycles) FROM cpu_usage_all) * 100 AS cpu_percentage
+FROM
+ cpu_usage_all
+ORDER BY cpu_mcycles DESC LIMIT 6;
+
+
+-- Record the output for populating the proto.
+DROP VIEW IF EXISTS {{output_table_name}};
+CREATE VIEW {{output_table_name}} AS
+SELECT AndroidMultiuserMetric_EventData(
+ 'duration_ms', (
+ SELECT duration_ms
+ FROM multiuser_timing
+ ),
+ 'cpu_usage', (
+ SELECT RepeatedField(
+ AndroidMultiuserMetric_EventData_CpuUsage(
+ 'user_id', user_id,
+ 'process_name', process_name,
+ 'cpu_mcycles', cpu_mcycles,
+ 'cpu_percentage', cpu_percentage
+ )
+ )
+ FROM cpu_usage
+ )
+);
diff --git a/src/trace_processor/metrics/android/android_powrails.sql b/src/trace_processor/metrics/android/android_powrails.sql
index d05324a..656cb15 100644
--- a/src/trace_processor/metrics/android/android_powrails.sql
+++ b/src/trace_processor/metrics/android/android_powrails.sql
@@ -22,6 +22,28 @@
JOIN counter_track t on c.track_id = t.id
WHERE name LIKE 'power.%';
+DROP VIEW IF EXISTS avg_used_powers;
+CREATE VIEW avg_used_powers AS
+SELECT
+ name,
+ avg_used_power
+FROM (
+ SELECT
+ name,
+ (LEAD(value) OVER (PARTITION BY name ORDER BY ts) - value) /
+ (LEAD(ts) OVER (PARTITION BY name ORDER BY ts) - ts) AS avg_used_power
+ FROM (
+ SELECT name, MIN(ts) AS ts, value
+ FROM power_rails_counters
+ GROUP BY name
+ UNION
+ SELECT name, MAX(ts) AS ts, value
+ FROM power_rails_counters
+ GROUP BY name
+ )
+ ORDER BY name, ts
+) WHERE avg_used_power IS NOT NULL;
+
DROP VIEW IF EXISTS power_rails_view;
CREATE VIEW power_rails_view AS
WITH RECURSIVE name AS (SELECT DISTINCT name FROM power_rails_counters)
@@ -35,7 +57,9 @@
'timestamp_ms', ts,
'energy_uws', value
)
- )
+ ),
+ 'avg_used_power_mw', (SELECT avg_used_power FROM avg_used_powers
+ WHERE avg_used_powers.name = power_rails_counters.name)
) AS power_rails_proto
FROM power_rails_counters
GROUP BY name
diff --git a/src/trace_processor/metrics/android/android_startup.sql b/src/trace_processor/metrics/android/android_startup.sql
index b97a2ab..d347a50 100644
--- a/src/trace_processor/metrics/android/android_startup.sql
+++ b/src/trace_processor/metrics/android/android_startup.sql
@@ -127,6 +127,8 @@
launch_threads.launch_id AS launch_id,
launch_threads.utid AS utid,
launch_threads.thread_name AS thread_name,
+ slice.id AS slice_id,
+ slice.arg_set_id AS arg_set_id,
slice.name AS slice_name,
slice.ts AS slice_ts,
slice.dur AS slice_dur
@@ -268,12 +270,36 @@
DROP TABLE IF EXISTS long_binder_transactions;
CREATE TABLE long_binder_transactions AS
SELECT
- launch_id, slice_dur, thread_name
+ slice_id, arg_set_id, launch_id, slice_dur, thread_name
FROM
main_process_slice_unaggregated
WHERE
slice_name = 'binder transaction'
- AND slice_dur >= 1e8;
+ AND slice_dur >= 5e7;
+
+DROP TABLE IF EXISTS binder_to_destination_process;
+CREATE TABLE binder_to_destination_process AS
+SELECT
+ s.slice_id, process.name AS destination_process
+FROM long_binder_transactions s
+JOIN args USING(arg_set_id)
+JOIN process ON(args.int_value = process.pid)
+WHERE args.key = 'destination process';
+
+-- Enriched binder transactions.
+DROP TABLE IF EXISTS long_binder_transactions_enriched;
+CREATE TABLE long_binder_transactions_enriched AS
+SELECT
+ s.launch_id,
+ s.slice_dur,
+ s.thread_name,
+ EXTRACT_ARG(s.arg_set_id, 'destination name') AS destination_thread,
+ bdp.destination_process,
+ EXTRACT_ARG(s.arg_set_id, 'flags') AS flags,
+ EXTRACT_ARG(s.arg_set_id, 'code') AS code,
+ EXTRACT_ARG(s.arg_set_id, 'data_size') AS data_size
+FROM long_binder_transactions s
+LEFT JOIN binder_to_destination_process bdp USING(slice_id);
DROP VIEW IF EXISTS startup_view;
CREATE VIEW startup_view AS
@@ -310,9 +336,14 @@
'dur_ns', lbt.slice_dur,
'dur_ms', lbt.slice_dur / 1e6
),
- 'thread', lbt.thread_name
+ 'thread', lbt.thread_name,
+ 'destination_thread', lbt.destination_thread,
+ 'destination_process', lbt.destination_process,
+ 'flags', lbt.flags,
+ 'code', lbt.code,
+ 'data_size', lbt.data_size
))
- FROM long_binder_transactions lbt
+ FROM long_binder_transactions_enriched lbt
WHERE lbt.launch_id = launches.id
),
'zygote_new_process', EXISTS(SELECT TRUE FROM zygote_forks_by_id WHERE id = launches.id),
diff --git a/src/trace_processor/metrics/android/android_surfaceflinger.sql b/src/trace_processor/metrics/android/android_surfaceflinger.sql
index b0d761f..daa9fda 100644
--- a/src/trace_processor/metrics/android/android_surfaceflinger.sql
+++ b/src/trace_processor/metrics/android/android_surfaceflinger.sql
@@ -40,6 +40,52 @@
FROM frame_missed
WHERE value = 1 AND ts IS NOT NULL;
+DROP VIEW IF EXISTS surfaceflinger_track;
+CREATE VIEW surfaceflinger_track AS
+SELECT tr.id AS track_id, t.utid, t.tid
+FROM process p JOIN thread t ON p.upid = t.upid
+ JOIN thread_track tr ON tr.utid = t.utid
+WHERE p.cmdline='/system/bin/surfaceflinger';
+
+DROP VIEW IF EXISTS gpu_waiting_start;
+CREATE VIEW gpu_waiting_start AS
+SELECT
+ CAST(SUBSTR(s.name, 28) AS UINT32) AS fence_id,
+ ts AS start_ts
+FROM slices s JOIN surfaceflinger_track t ON s.track_id = t.track_id
+WHERE s.name LIKE 'Trace GPU completion fence %';
+
+DROP VIEW IF EXISTS gpu_waiting_end;
+CREATE VIEW gpu_waiting_end AS
+SELECT
+ CAST(SUBSTR(s.name, 28) AS UINT32) AS fence_id,
+ dur,
+ ts+dur AS end_ts
+FROM slices s JOIN surfaceflinger_track t ON s.track_id = t.track_id
+WHERE s.name LIKE 'waiting for GPU completion %';
+
+DROP VIEW IF EXISTS gpu_waiting_span;
+CREATE VIEW gpu_waiting_span AS
+SELECT
+ fence_id,
+ ts,
+ dur
+FROM (
+ SELECT
+ fence_id,
+ ts,
+ LEAD(ts) OVER (ORDER BY fence_id, event_type) - ts AS dur,
+ LEAD(fence_id) OVER (ORDER BY fence_id, event_type) AS next_fence_id,
+ event_type
+ FROM (
+ SELECT fence_id, start_ts AS ts, 0 AS event_type FROM gpu_waiting_start
+ UNION
+ SELECT fence_id, end_ts AS ts, 1 AS event_type FROM gpu_waiting_end
+ )
+ ORDER BY fence_id, event_type
+)
+WHERE event_type = 0 AND fence_id = next_fence_id;
+
DROP VIEW IF EXISTS android_surfaceflinger_output;
CREATE VIEW android_surfaceflinger_output AS
SELECT
@@ -49,5 +95,9 @@
'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)
+ 'missed_gpu_frame_rate', (SELECT AVG(value) FROM gpu_frame_missed),
+ 'gpu_invocations', (SELECT COUNT(1) FROM gpu_waiting_end),
+ 'avg_gpu_waiting_dur_ms', (SELECT AVG(dur)/1e6 FROM gpu_waiting_span),
+ 'total_non_empty_gpu_waiting_dur_ms',
+ (SELECT SUM(dur)/1e6 FROM gpu_waiting_end)
);
diff --git a/src/trace_processor/metrics/android/android_sysui_cuj.sql b/src/trace_processor/metrics/android/android_sysui_cuj.sql
index e5b4079..6b5c58d 100644
--- a/src/trace_processor/metrics/android/android_sysui_cuj.sql
+++ b/src/trace_processor/metrics/android/android_sysui_cuj.sql
@@ -34,7 +34,7 @@
AND slice.dur > 0
AND (
process.name LIKE 'com.google.android%'
- OR process.name = 'com.android.systemui')
+ OR process.name LIKE 'com.android.%')
ORDER BY ts desc
LIMIT 1;
@@ -43,6 +43,67 @@
'table_name_prefix', 'android_sysui_cuj',
'process_allowlist_table', 'android_sysui_cuj_last_cuj');
+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.*,
+ lag(slices.ts_end) OVER (ORDER BY vsync ASC) as ts_prev_frame_end
+FROM android_sysui_cuj_do_frame_slices slices
+JOIN android_sysui_cuj_last_cuj last_cuj
+ON ts + slices.dur >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
+
+DROP TABLE IF EXISTS android_sysui_cuj_vsync_boundaries;
+CREATE TABLE android_sysui_cuj_vsync_boundaries AS
+SELECT MIN(vsync) as vsync_min, MAX(vsync) as vsync_max
+FROM android_sysui_cuj_do_frame_slices_in_cuj;
+
+DROP TABLE IF EXISTS android_sysui_cuj_frame_timeline_events;
+CREATE TABLE android_sysui_cuj_frame_timeline_events AS
+ SELECT
+ actual.layer_name as layer_name,
+ CAST(actual.name as INTEGER) 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 android_sysui_cuj_last_cuj cuj
+ JOIN actual_frame_timeline_slice actual USING (upid)
+ JOIN android_sysui_cuj_vsync_boundaries vsync
+ ON CAST(actual.name as INTEGER) >= vsync.vsync_min
+ AND CAST(actual.name as INTEGER) <= vsync.vsync_max;
+
+-- Adjust the timestamp when we consider the work on a given frame started,
+-- by looking at the time the previous frame finished on the main thread
+-- and the timing from the actual timeline.
+-- This is to detect cases where we started doFrame late due to some other work
+-- occupying the main thread.
+DROP TABLE IF EXISTS android_sysui_cuj_do_frame_slices_in_cuj_adjusted;
+CREATE TABLE android_sysui_cuj_do_frame_slices_in_cuj_adjusted AS
+SELECT
+ slices.*,
+ CASE
+ WHEN fte.ts_actual IS NULL
+ THEN ts
+ ELSE MAX(COALESCE(slices.ts_prev_frame_end, 0), fte.ts_actual)
+ END as ts_adjusted
+FROM android_sysui_cuj_do_frame_slices_in_cuj slices
+LEFT JOIN android_sysui_cuj_frame_timeline_events fte
+ON slices.vsync = fte.vsync
+-- In rare cases there is a clock drift after device suspends
+-- This may cause the actual/expected timeline to be misaligned with the rest
+-- of the trace for a short period.
+-- Do not use the timelines if it seems that this happened.
+AND slices.ts >= fte.ts_actual AND slices.ts <= fte.ts_actual + fte.dur_actual;
+
+DROP TABLE IF EXISTS android_sysui_cuj_ts_boundaries;
+CREATE TABLE android_sysui_cuj_ts_boundaries AS
+SELECT ts, ts_end - ts as dur, ts_end FROM (
+SELECT
+(SELECT ts_adjusted FROM android_sysui_cuj_do_frame_slices_in_cuj_adjusted ORDER BY ts ASC LIMIT 1) as ts,
+(SELECT ts FROM android_sysui_cuj_do_frame_slices_in_cuj ORDER BY ts DESC LIMIT 1) +
+(SELECT dur_actual FROM android_sysui_cuj_frame_timeline_events ORDER BY vsync DESC LIMIT 1) as ts_end);
+
DROP VIEW IF EXISTS android_sysui_cuj_thread;
CREATE VIEW android_sysui_cuj_thread AS
SELECT
@@ -58,50 +119,44 @@
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
+ slices.*,
+ slices.ts + slices.dur AS ts_end
+FROM slices
+JOIN thread_track ON slices.track_id = thread_track.id
JOIN android_sysui_cuj_thread thread USING (utid)
-JOIN android_sysui_cuj_last_cuj last_cuj
-ON ts + slice.dur >= last_cuj.ts_start AND ts <= last_cuj.ts_end
-WHERE slice.dur > 0;
+JOIN android_sysui_cuj_ts_boundaries cuj_boundaries
+ON slices.ts + slices.dur >= cuj_boundaries.ts AND slices.ts <= cuj_boundaries.ts_end
+WHERE slices.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 + slices.dur >= 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 + slices.dur >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
+JOIN android_sysui_cuj_ts_boundaries cuj_boundaries
+ON slices.ts + slices.dur >= cuj_boundaries.ts AND slices.ts <= cuj_boundaries.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 + slices.dur >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
+JOIN android_sysui_cuj_ts_boundaries cuj_boundaries
+ON slices.ts >= cuj_boundaries.ts AND slices.ts <= cuj_boundaries.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 + slices.dur >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
+JOIN android_sysui_cuj_ts_boundaries cuj_boundaries
+ON slices.ts >= cuj_boundaries.ts AND slices.ts <= cuj_boundaries.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 + slices.dur >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
+JOIN android_sysui_cuj_ts_boundaries cuj_boundaries
+ON slices.ts >= cuj_boundaries.ts AND slices.ts <= cuj_boundaries.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 + slices.dur >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
+JOIN android_sysui_cuj_ts_boundaries cuj_boundaries
+ON slices.ts >= cuj_boundaries.ts AND slices.ts <= cuj_boundaries.ts_end;
DROP TABLE IF EXISTS android_sysui_cuj_jit_slices;
CREATE TABLE android_sysui_cuj_jit_slices AS
@@ -111,26 +166,6 @@
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
- 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 (
@@ -151,13 +186,13 @@
frame_boundaries AS (
-- Match main thread doFrame with RT DrawFrame and optional GPU Completion
SELECT
- mts.ts as mts_ts,
+ mts.ts_adjusted as mts_ts,
mts.ts_end as mts_ts_end,
- mts.dur as mts_dur,
+ mts.ts_end - mts.ts_adjusted 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
+ FROM android_sysui_cuj_do_frame_slices_in_cuj_adjusted 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
diff --git a/src/trace_processor/metrics/android/android_sysui_cuj_jank_query.sql b/src/trace_processor/metrics/android/android_sysui_cuj_jank_query.sql
new file mode 100644
index 0000000..0ed0465
--- /dev/null
+++ b/src/trace_processor/metrics/android/android_sysui_cuj_jank_query.sql
@@ -0,0 +1,49 @@
+--
+-- 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 {{table_name_prefix}}_relevant_slices_in_cuj;
+CREATE VIEW {{table_name_prefix}}_relevant_slices_in_cuj AS
+SELECT slice.ts, slice.dur FROM {{relevant_slices_table}} slice
+JOIN android_sysui_cuj_ts_boundaries boundaries
+ON slice.ts + slice.dur >= boundaries.ts AND slice.ts <= boundaries.ts_end;
+
+DROP TABLE IF EXISTS {{table_name_prefix}}_cuj_join_table;
+CREATE VIRTUAL TABLE {{table_name_prefix}}_cuj_join_table
+USING span_join(
+ android_sysui_cuj_ts_boundaries,
+ {{table_name_prefix}}_relevant_slices_in_cuj);
+
+DROP TABLE IF EXISTS {{table_name_prefix}}_frame_join_table;
+CREATE VIRTUAL TABLE {{table_name_prefix}}_frame_join_table
+USING span_join(
+ android_sysui_cuj_missed_frames_hwui_times partitioned frame_number,
+ {{table_name_prefix}}_relevant_slices_in_cuj);
+
+DROP VIEW IF EXISTS {{table_name_prefix}}_per_cuj_output_data;
+CREATE VIEW {{table_name_prefix}}_per_cuj_output_data AS
+SELECT SUM(dur) as dur_sum
+FROM {{table_name_prefix}}_cuj_join_table;
+
+DROP VIEW IF EXISTS {{table_name_prefix}}_per_frame_output_data;
+CREATE VIEW {{table_name_prefix}}_per_frame_output_data AS
+SELECT
+f.frame_number,
+f.vsync,
+f.dur_frame,
+f.app_missed,
+SUM(jt.dur) as dur_sum
+FROM android_sysui_cuj_missed_frames f
+JOIN {{table_name_prefix}}_frame_join_table jt USING (frame_number)
+GROUP BY f.frame_number, f.vsync, f.dur_frame, f.app_missed;
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..160726b 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
@@ -135,72 +135,63 @@
)
);
--- 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
-SELECT
- ts,
- LAG(ts) OVER (ORDER BY ts) AS lag_ts
-FROM (
- 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
SELECT
ts,
- ts - lag_ts AS dur,
- upid,
- core_type,
utid,
- -- We need globally unique track names so add the utid even when we
- -- know the name. But when we don't, also use the tid because that's what
- -- the rest of the UI does.
- IFNULL(thread.name, 'Thread ' || thread.tid) || ' (' || thread.utid || ')'
- AS thread_track_name,
+ core_type,
freq,
- runtime_ms_counter - LAG(runtime_ms_counter)
- OVER (PARTITION BY core_type, utid, freq ORDER BY ts) AS runtime_ms
+ time_in_state_cpu,
+ runtime_ms_counter - LAG(runtime_ms_counter) OVER win AS runtime_ms_diff
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 thread using (utid);
+WINDOW win AS (PARTITION BY utid, core_type, time_in_state_cpu, freq ORDER BY ts);
+
+DROP VIEW IF EXISTS android_thread_time_in_state_by_core_type;
+CREATE VIEW android_thread_time_in_state_by_core_type AS
+SELECT
+ ts,
+ utid,
+ core_type,
+ freq,
+ SUM(runtime_ms_diff) runtime_ms_diff
+FROM android_thread_time_in_state_event_raw
+GROUP BY ts, utid, core_type, freq
+HAVING runtime_ms_diff > 0;
DROP VIEW IF EXISTS android_thread_time_in_state_event_thread;
CREATE VIEW android_thread_time_in_state_event_thread AS
SELECT
- 'counter' AS track_type,
- thread_track_name || ' (' || core_type || ' core)' as track_name,
+ -- We need globally unique track names so add the utid even when we
+ -- know the name. But when we don't, also use the tid because that's what
+ -- the rest of the UI does.
+ IFNULL(thread.name, 'Thread ' || thread.tid) || ' (' || thread.utid || ')'
+ || ' (' || core_type || ' core) mcycles' AS track_name,
ts,
- dur,
upid,
- sum(runtime_ms * freq) as ms_freq
-FROM android_thread_time_in_state_event_raw
-WHERE runtime_ms IS NOT NULL
- AND dur != 0
-GROUP BY track_type, track_name, ts, dur, upid;
+ SUM(runtime_ms_diff * freq) OVER win AS cycles
+FROM android_thread_time_in_state_by_core_type
+JOIN thread USING (utid)
+GROUP BY ts, upid, track_name
+WINDOW win AS (PARTITION BY utid ORDER BY ts);
DROP VIEW IF EXISTS android_thread_time_in_state_event_global;
CREATE VIEW android_thread_time_in_state_event_global AS
SELECT
- 'counter' AS track_type,
- 'Total ' || core_type || ' core cycles / sec' as track_name,
+ 'Total ' || core_type || ' core mcycles' as track_name,
ts,
- dur,
0 AS upid,
- SUM(runtime_ms * freq) AS ms_freq
-FROM android_thread_time_in_state_event_raw
-WHERE runtime_ms IS NOT NULL
-GROUP BY ts, track_name;
+ SUM(runtime_ms_diff * freq) OVER win as cycles
+FROM android_thread_time_in_state_by_core_type
+GROUP BY ts, track_name
+WINDOW win AS (ORDER BY ts);
DROP TABLE IF EXISTS android_thread_time_in_state_event;
CREATE TABLE android_thread_time_in_state_event AS
-SELECT track_type, track_name, ts, dur, upid, ms_freq * 1000000 / dur AS value
+SELECT 'counter' as track_type, track_name, upid, ts, cycles / 1000000.0 AS value
FROM android_thread_time_in_state_event_thread
UNION ALL
-SELECT track_type, track_name, ts, dur, upid, ms_freq * 1000000 / dur AS value
+SELECT 'counter' as track_type, track_name, upid, ts, cycles / 1000000.0 AS value
FROM android_thread_time_in_state_event_global
-- Biggest values at top of list in UI.
ORDER BY value DESC;
diff --git a/src/trace_processor/metrics/android/android_trace_quality.sql b/src/trace_processor/metrics/android/android_trace_quality.sql
new file mode 100644
index 0000000..a68c053
--- /dev/null
+++ b/src/trace_processor/metrics/android/android_trace_quality.sql
@@ -0,0 +1,35 @@
+--
+-- 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 android_trace_quality_failures;
+CREATE VIEW android_trace_quality_failures AS
+-- Check that all the sched slices are less than 1 week long.
+SELECT
+ 'sched_slice_too_long' as name,
+ MAX(dur) > 1 * 7 * 24 * 60 * 60 * 1000 * 1000 * 1000 as failed
+FROM sched;
+
+DROP VIEW IF EXISTS android_trace_quality_output;
+CREATE VIEW android_trace_quality_output AS
+SELECT AndroidTraceQualityMetric(
+ 'failures', (
+ SELECT RepeatedField(AndroidTraceQualityMetric_Failure(
+ 'name', name
+ ))
+ FROM android_trace_quality_failures
+ WHERE failed
+ )
+);
diff --git a/src/trace_processor/metrics/android/g2d_duration.sql b/src/trace_processor/metrics/android/g2d_duration.sql
index 7d96d06..b4a167b 100644
--- a/src/trace_processor/metrics/android/g2d_duration.sql
+++ b/src/trace_processor/metrics/android/g2d_duration.sql
@@ -45,9 +45,9 @@
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),
+ 'max_dur_ms', MAX(dur) / 1e6,
+ 'min_dur_ms', MIN(dur) / 1e6,
+ 'avg_dur_ms', AVG(dur) / 1e6,
'frame_count', COUNT(*),
'error_count', (SELECT COUNT(*) FROM g2d_{{g2d_type}}_errors e WHERE e.track_name = g.track_name)
) AS instance
@@ -59,9 +59,9 @@
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),
+ 'max_dur_ms', MAX(dur) / 1e6,
+ 'min_dur_ms', MIN(dur) / 1e6,
+ 'avg_dur_ms', AVG(dur) / 1e6,
'frame_count', COUNT(*),
'error_count', (SELECT COUNT(*) FROM g2d_{{g2d_type}}_errors)
) AS metric
diff --git a/src/trace_processor/metrics/android/gpu_counter_span_view.sql b/src/trace_processor/metrics/android/gpu_counter_span_view.sql
new file mode 100644
index 0000000..7a40fd0
--- /dev/null
+++ b/src/trace_processor/metrics/android/gpu_counter_span_view.sql
@@ -0,0 +1,27 @@
+--
+-- 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 {{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,
+ gpu_id,
+ value AS {{table_name}}_val
+FROM counter c JOIN gpu_counter_track t
+ ON t.id = c.track_id
+WHERE name = '{{counter_name}}' AND gpu_id IS NOT NULL;
diff --git a/src/trace_processor/metrics/android/power_profile_data.sql b/src/trace_processor/metrics/android/power_profile_data.sql
index 5ea96ea..c124c8a 100644
--- a/src/trace_processor/metrics/android/power_profile_data.sql
+++ b/src/trace_processor/metrics/android/power_profile_data.sql
@@ -1363,4 +1363,230 @@
("flame", 7, 2, 2534400, 160.73),
("flame", 7, 2, 2649600, 175.5),
("flame", 7, 2, 2745600, 186.29),
-("flame", 7, 2, 2841600, 223.89);
+("flame", 7, 2, 2841600, 223.89),
+("sunfish", 0, 0, 300000, 5.75833333333),
+("sunfish", 0, 0, 576000, 7.76166666667),
+("sunfish", 0, 0, 768000, 9.14),
+("sunfish", 0, 0, 1017600, 11.36),
+("sunfish", 0, 0, 1248000, 13.45),
+("sunfish", 0, 0, 1324800, 14.4333333333),
+("sunfish", 0, 0, 1497600, 16.5216666667),
+("sunfish", 0, 0, 1612800, 18.5083333333),
+("sunfish", 0, 0, 1708800, 19.9316666667),
+("sunfish", 0, 0, 1804800, 21.4083333333),
+("sunfish", 1, 0, 300000, 5.75833333333),
+("sunfish", 1, 0, 576000, 7.76166666667),
+("sunfish", 1, 0, 768000, 9.14),
+("sunfish", 1, 0, 1017600, 11.36),
+("sunfish", 1, 0, 1248000, 13.45),
+("sunfish", 1, 0, 1324800, 14.4333333333),
+("sunfish", 1, 0, 1497600, 16.5216666667),
+("sunfish", 1, 0, 1612800, 18.5083333333),
+("sunfish", 1, 0, 1708800, 19.9316666667),
+("sunfish", 1, 0, 1804800, 21.4083333333),
+("sunfish", 2, 0, 300000, 5.75833333333),
+("sunfish", 2, 0, 576000, 7.76166666667),
+("sunfish", 2, 0, 768000, 9.14),
+("sunfish", 2, 0, 1017600, 11.36),
+("sunfish", 2, 0, 1248000, 13.45),
+("sunfish", 2, 0, 1324800, 14.4333333333),
+("sunfish", 2, 0, 1497600, 16.5216666667),
+("sunfish", 2, 0, 1612800, 18.5083333333),
+("sunfish", 2, 0, 1708800, 19.9316666667),
+("sunfish", 2, 0, 1804800, 21.4083333333),
+("sunfish", 3, 0, 300000, 5.75833333333),
+("sunfish", 3, 0, 576000, 7.76166666667),
+("sunfish", 3, 0, 768000, 9.14),
+("sunfish", 3, 0, 1017600, 11.36),
+("sunfish", 3, 0, 1248000, 13.45),
+("sunfish", 3, 0, 1324800, 14.4333333333),
+("sunfish", 3, 0, 1497600, 16.5216666667),
+("sunfish", 3, 0, 1612800, 18.5083333333),
+("sunfish", 3, 0, 1708800, 19.9316666667),
+("sunfish", 3, 0, 1804800, 21.4083333333),
+("sunfish", 4, 0, 300000, 5.75833333333),
+("sunfish", 4, 0, 576000, 7.76166666667),
+("sunfish", 4, 0, 768000, 9.14),
+("sunfish", 4, 0, 1017600, 11.36),
+("sunfish", 4, 0, 1248000, 13.45),
+("sunfish", 4, 0, 1324800, 14.4333333333),
+("sunfish", 4, 0, 1497600, 16.5216666667),
+("sunfish", 4, 0, 1612800, 18.5083333333),
+("sunfish", 4, 0, 1708800, 19.9316666667),
+("sunfish", 4, 0, 1804800, 21.4083333333),
+("sunfish", 5, 0, 300000, 5.75833333333),
+("sunfish", 5, 0, 576000, 7.76166666667),
+("sunfish", 5, 0, 768000, 9.14),
+("sunfish", 5, 0, 1017600, 11.36),
+("sunfish", 5, 0, 1248000, 13.45),
+("sunfish", 5, 0, 1324800, 14.4333333333),
+("sunfish", 5, 0, 1497600, 16.5216666667),
+("sunfish", 5, 0, 1612800, 18.5083333333),
+("sunfish", 5, 0, 1708800, 19.9316666667),
+("sunfish", 5, 0, 1804800, 21.4083333333),
+("sunfish", 6, 1, 300000, 21.115),
+("sunfish", 6, 1, 652800, 28.46),
+("sunfish", 6, 1, 806400, 31.705),
+("sunfish", 6, 1, 979200, 36.515),
+("sunfish", 6, 1, 1094400, 40.19),
+("sunfish", 6, 1, 1209600, 43.585),
+("sunfish", 6, 1, 1324800, 48.275),
+("sunfish", 6, 1, 1555200, 62.805),
+("sunfish", 6, 1, 1708800, 72.755),
+("sunfish", 6, 1, 1843200, 91.47),
+("sunfish", 6, 1, 1939200, 99.46),
+("sunfish", 6, 1, 2169600, 119.27),
+("sunfish", 6, 1, 2208000, 133.105),
+("sunfish", 7, 1, 300000, 21.115),
+("sunfish", 7, 1, 652800, 28.46),
+("sunfish", 7, 1, 806400, 31.705),
+("sunfish", 7, 1, 979200, 36.515),
+("sunfish", 7, 1, 1094400, 40.19),
+("sunfish", 7, 1, 1209600, 43.585),
+("sunfish", 7, 1, 1324800, 48.275),
+("sunfish", 7, 1, 1555200, 62.805),
+("sunfish", 7, 1, 1708800, 72.755),
+("sunfish", 7, 1, 1843200, 91.47),
+("sunfish", 7, 1, 1939200, 99.46),
+("sunfish", 7, 1, 2169600, 119.27),
+("sunfish", 7, 1, 2208000, 133.105),
+("redfin", 0, 0, 300000, 6.98666666667),
+("redfin", 0, 0, 576000, 9.93166666667),
+("redfin", 0, 0, 614400, 10.3216666667),
+("redfin", 0, 0, 864000, 13.31),
+("redfin", 0, 0, 1075200, 15.9866666667),
+("redfin", 0, 0, 1363200, 20.3283333333),
+("redfin", 0, 0, 1516800, 23.4533333333),
+("redfin", 0, 0, 1651200, 26.53),
+("redfin", 0, 0, 1804800, 29.365),
+("redfin", 1, 0, 300000, 6.98666666667),
+("redfin", 1, 0, 576000, 9.93166666667),
+("redfin", 1, 0, 614400, 10.3216666667),
+("redfin", 1, 0, 864000, 13.31),
+("redfin", 1, 0, 1075200, 15.9866666667),
+("redfin", 1, 0, 1363200, 20.3283333333),
+("redfin", 1, 0, 1516800, 23.4533333333),
+("redfin", 1, 0, 1651200, 26.53),
+("redfin", 1, 0, 1804800, 29.365),
+("redfin", 2, 0, 300000, 6.98666666667),
+("redfin", 2, 0, 576000, 9.93166666667),
+("redfin", 2, 0, 614400, 10.3216666667),
+("redfin", 2, 0, 864000, 13.31),
+("redfin", 2, 0, 1075200, 15.9866666667),
+("redfin", 2, 0, 1363200, 20.3283333333),
+("redfin", 2, 0, 1516800, 23.4533333333),
+("redfin", 2, 0, 1651200, 26.53),
+("redfin", 2, 0, 1804800, 29.365),
+("redfin", 3, 0, 300000, 6.98666666667),
+("redfin", 3, 0, 576000, 9.93166666667),
+("redfin", 3, 0, 614400, 10.3216666667),
+("redfin", 3, 0, 864000, 13.31),
+("redfin", 3, 0, 1075200, 15.9866666667),
+("redfin", 3, 0, 1363200, 20.3283333333),
+("redfin", 3, 0, 1516800, 23.4533333333),
+("redfin", 3, 0, 1651200, 26.53),
+("redfin", 3, 0, 1804800, 29.365),
+("redfin", 4, 0, 300000, 6.98666666667),
+("redfin", 4, 0, 576000, 9.93166666667),
+("redfin", 4, 0, 614400, 10.3216666667),
+("redfin", 4, 0, 864000, 13.31),
+("redfin", 4, 0, 1075200, 15.9866666667),
+("redfin", 4, 0, 1363200, 20.3283333333),
+("redfin", 4, 0, 1516800, 23.4533333333),
+("redfin", 4, 0, 1651200, 26.53),
+("redfin", 4, 0, 1804800, 29.365),
+("redfin", 5, 0, 300000, 6.98666666667),
+("redfin", 5, 0, 576000, 9.93166666667),
+("redfin", 5, 0, 614400, 10.3216666667),
+("redfin", 5, 0, 864000, 13.31),
+("redfin", 5, 0, 1075200, 15.9866666667),
+("redfin", 5, 0, 1363200, 20.3283333333),
+("redfin", 5, 0, 1516800, 23.4533333333),
+("redfin", 5, 0, 1651200, 26.53),
+("redfin", 5, 0, 1804800, 29.365),
+("redfin", 6, 1, 652800, 32.13),
+("redfin", 6, 1, 940800, 35.98),
+("redfin", 6, 1, 1152000, 40.03),
+("redfin", 6, 1, 1478400, 51.02),
+("redfin", 6, 1, 1728000, 77.06),
+("redfin", 6, 1, 1900800, 86.25),
+("redfin", 6, 1, 2092800, 97.3),
+("redfin", 6, 1, 2208000, 101.61),
+("redfin", 7, 2, 806400, 56.44),
+("redfin", 7, 2, 1094400, 65.72),
+("redfin", 7, 2, 1401600, 77.01),
+("redfin", 7, 2, 1766400, 104.91),
+("redfin", 7, 2, 1996800, 112.35),
+("redfin", 7, 2, 2188800, 118.53),
+("redfin", 7, 2, 2304000, 122.34),
+("redfin", 7, 2, 2400000, 135.0),
+("bramble", 0, 0, 300000, 6.98666666667),
+("bramble", 0, 0, 576000, 9.93166666667),
+("bramble", 0, 0, 614400, 10.3216666667),
+("bramble", 0, 0, 864000, 13.31),
+("bramble", 0, 0, 1075200, 15.9866666667),
+("bramble", 0, 0, 1363200, 20.3283333333),
+("bramble", 0, 0, 1516800, 23.4533333333),
+("bramble", 0, 0, 1651200, 26.53),
+("bramble", 0, 0, 1804800, 29.365),
+("bramble", 1, 0, 300000, 6.98666666667),
+("bramble", 1, 0, 576000, 9.93166666667),
+("bramble", 1, 0, 614400, 10.3216666667),
+("bramble", 1, 0, 864000, 13.31),
+("bramble", 1, 0, 1075200, 15.9866666667),
+("bramble", 1, 0, 1363200, 20.3283333333),
+("bramble", 1, 0, 1516800, 23.4533333333),
+("bramble", 1, 0, 1651200, 26.53),
+("bramble", 1, 0, 1804800, 29.365),
+("bramble", 2, 0, 300000, 6.98666666667),
+("bramble", 2, 0, 576000, 9.93166666667),
+("bramble", 2, 0, 614400, 10.3216666667),
+("bramble", 2, 0, 864000, 13.31),
+("bramble", 2, 0, 1075200, 15.9866666667),
+("bramble", 2, 0, 1363200, 20.3283333333),
+("bramble", 2, 0, 1516800, 23.4533333333),
+("bramble", 2, 0, 1651200, 26.53),
+("bramble", 2, 0, 1804800, 29.365),
+("bramble", 3, 0, 300000, 6.98666666667),
+("bramble", 3, 0, 576000, 9.93166666667),
+("bramble", 3, 0, 614400, 10.3216666667),
+("bramble", 3, 0, 864000, 13.31),
+("bramble", 3, 0, 1075200, 15.9866666667),
+("bramble", 3, 0, 1363200, 20.3283333333),
+("bramble", 3, 0, 1516800, 23.4533333333),
+("bramble", 3, 0, 1651200, 26.53),
+("bramble", 3, 0, 1804800, 29.365),
+("bramble", 4, 0, 300000, 6.98666666667),
+("bramble", 4, 0, 576000, 9.93166666667),
+("bramble", 4, 0, 614400, 10.3216666667),
+("bramble", 4, 0, 864000, 13.31),
+("bramble", 4, 0, 1075200, 15.9866666667),
+("bramble", 4, 0, 1363200, 20.3283333333),
+("bramble", 4, 0, 1516800, 23.4533333333),
+("bramble", 4, 0, 1651200, 26.53),
+("bramble", 4, 0, 1804800, 29.365),
+("bramble", 5, 0, 300000, 6.98666666667),
+("bramble", 5, 0, 576000, 9.93166666667),
+("bramble", 5, 0, 614400, 10.3216666667),
+("bramble", 5, 0, 864000, 13.31),
+("bramble", 5, 0, 1075200, 15.9866666667),
+("bramble", 5, 0, 1363200, 20.3283333333),
+("bramble", 5, 0, 1516800, 23.4533333333),
+("bramble", 5, 0, 1651200, 26.53),
+("bramble", 5, 0, 1804800, 29.365),
+("bramble", 6, 1, 652800, 32.13),
+("bramble", 6, 1, 940800, 35.98),
+("bramble", 6, 1, 1152000, 40.03),
+("bramble", 6, 1, 1478400, 51.02),
+("bramble", 6, 1, 1728000, 77.06),
+("bramble", 6, 1, 1900800, 86.25),
+("bramble", 6, 1, 2092800, 97.3),
+("bramble", 6, 1, 2208000, 101.61),
+("bramble", 7, 2, 806400, 56.44),
+("bramble", 7, 2, 1094400, 65.72),
+("bramble", 7, 2, 1401600, 77.01),
+("bramble", 7, 2, 1766400, 104.91),
+("bramble", 7, 2, 1996800, 112.35),
+("bramble", 7, 2, 2188800, 118.53),
+("bramble", 7, 2, 2304000, 122.34),
+("bramble", 7, 2, 2400000, 135.0);
\ No newline at end of file
diff --git a/src/trace_processor/metrics/android/profiler_smaps.sql b/src/trace_processor/metrics/android/profiler_smaps.sql
new file mode 100644
index 0000000..481c74e
--- /dev/null
+++ b/src/trace_processor/metrics/android/profiler_smaps.sql
@@ -0,0 +1,53 @@
+--
+-- 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/process_metadata.sql') as unused;
+
+DROP VIEW IF EXISTS profiler_smaps_output;
+CREATE VIEW profiler_smaps_output AS
+ WITH base_stat_counts AS (
+ SELECT
+ ts,
+ upid,
+ path,
+ SUM(size_kb) size_kb,
+ SUM(private_dirty_kb) private_dirty_kb,
+ SUM(swap_kb) swap_kb
+ FROM profiler_smaps
+ GROUP BY 1, 2, 3
+ ORDER BY 4 DESC
+ ),
+ mapping_protos AS (
+ SELECT
+ ts,
+ upid,
+ RepeatedField(ProfilerSmaps_Mapping(
+ 'path', path,
+ 'size_kb', size_kb,
+ 'private_dirty_kb', private_dirty_kb,
+ 'swap_kb', swap_kb
+ )) mappings
+ FROM base_stat_counts
+ GROUP BY 1, 2
+ )
+ SELECT ProfilerSmaps(
+ 'instance', RepeatedField(
+ ProfilerSmaps_Instance(
+ 'process', process_metadata.metadata,
+ 'mappings', mappings
+ ))
+ )
+ FROM mapping_protos JOIN process_metadata USING (upid);
diff --git a/src/trace_processor/metrics/android/thread_counter_span_view.sql b/src/trace_processor/metrics/android/thread_counter_span_view.sql
new file mode 100644
index 0000000..da13734
--- /dev/null
+++ b/src/trace_processor/metrics/android/thread_counter_span_view.sql
@@ -0,0 +1,32 @@
+--
+-- 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 {{table_name}}_span;
+CREATE VIEW {{table_name}}_span AS
+SELECT
+ ts,
+ LEAD(ts, 1, (
+ SELECT IFNULL(
+ end_ts,
+ (SELECT end_ts FROM trace_bounds)
+ )
+ FROM thread th WHERE th.utid = t.utid) + 1
+ ) OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
+ utid,
+ value AS {{table_name}}_val
+FROM counter c JOIN thread_counter_track t
+ ON t.id = c.track_id
+WHERE name = '{{counter_name}}' AND utid IS NOT NULL;
diff --git a/src/trace_processor/metrics/chrome/gesture_flow_event.sql b/src/trace_processor/metrics/chrome/gesture_flow_event.sql
new file mode 100644
index 0000000..b9b54c2
--- /dev/null
+++ b/src/trace_processor/metrics/chrome/gesture_flow_event.sql
@@ -0,0 +1,258 @@
+--
+-- 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.
+--
+-- While handling a InputLatency::{{gesture_update}} event a sequence of Flows
+-- define the critical path from Beginning to End. This metric breaks down the
+-- flows for the same InputLatency::{{gesture_update}} 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 {{prefix}}_jank table which gives us all the {{gesture_update}}
+-- events we care about and labels them janky or not.
+SELECT RUN_METRIC('chrome/{{prefix}}_jank.sql');
+
+-- We get all latency_info that have valid trace_ids, And we make a synthetic
+-- one for the beginning of each {{gesture_update}} event so we can track the
+-- time between receiving the input and being converted into a gesture.
+--
+-- flows with a trace_id of -1 are incomplete and are difficult to reason about
+-- (especially if {{gesture_update}} flows end up getting -1). so ignore them
+-- for this table.
+DROP VIEW IF EXISTS {{prefix}}_latency_info_flow_step_and_ancestors;
+CREATE VIEW {{prefix}}_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 gesture_slice_id,
+ ts AS gesture_ts,
+ dur AS {{prefix}}_dur,
+ track_id AS gesture_track_id,
+ trace_id AS {{id_field}},
+ jank,
+ {{id_field}}
+ FROM {{prefix}}_jank
+ ) gesture ON
+ flow.trace_id = gesture.{{id_field}}
+ UNION ALL
+ SELECT
+ 'InputLatency::{{gesture_update}}' AS name,
+ id,
+ ts,
+ dur,
+ track_id,
+ trace_id,
+ 'AsyncBegin' AS step,
+ 'InputLatency::{{gesture_update}}' AS ancestor_name_zero,
+ id AS ancestor_id_zero,
+ ts AS ancestor_ts_zero,
+ 0 AS ancestor_dur_zero,
+ 'InputLatency::{{gesture_update}}' AS ancestor_name_one,
+ id AS ancestor_id_one,
+ ts AS ancestor_ts_one,
+ 0 AS ancestor_dur_one,
+ id AS gesture_slice_id,
+ ts AS gesture_ts,
+ dur AS {{prefix}}_dur,
+ track_id AS gesture_track_id,
+ trace_id AS {{id_field}},
+ jank,
+ {{id_field}}
+ FROM {{prefix}}_jank
+ ORDER BY {{id_field}} 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 {{prefix}}_latency_info_flow_step;
+CREATE VIEW {{prefix}}_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 {{prefix}}_latency_info_flow_step_and_ancestors;
+
+-- This is a heuristic to figure out which flow event properly joins this
+-- {{gesture_update}}. This heuristic is only needed in traces before we added
+-- {{id_field}}.
+--
+-- We select the first |ts| from a flow event after its corresponding
+-- {{gesture_update}} has ended. This allows us to use this |ts| to contain all
+-- flow events from the start of a particular gesture_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 gestures, but by
+-- limiting by the {{gesture_update}} 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 {{prefix}}_max_latency_info_ts_per_trace_id;
+CREATE VIEW {{prefix}}_max_latency_info_ts_per_trace_id AS
+ SELECT
+ gesture_slice_id,
+ MIN(ts) AS max_flow_ts
+ FROM {{prefix}}_latency_info_flow_step
+ WHERE
+ trace_id = {{id_field}} AND
+ ts > gesture_ts + {{prefix}}_dur
+ GROUP BY gesture_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 {{gesture_update}}. 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 {{prefix}}_latency_info_flow_step_filtered;
+CREATE TABLE {{prefix}}_latency_info_flow_step_filtered AS
+ SELECT
+ ROW_NUMBER() OVER (ORDER BY
+ flow.{{id_field}} ASC, trace_id ASC, ts ASC) AS row_number,
+ *
+ FROM
+ {{prefix}}_latency_info_flow_step flow JOIN
+ {{prefix}}_max_latency_info_ts_per_trace_id max_flow on
+ max_flow.gesture_slice_id = flow.gesture_slice_id
+ WHERE
+ ts >= gesture_ts AND
+ ts <= max_flow_ts
+ ORDER BY flow.{{id_field}} 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 {{prefix}}_latency_info_flow_null_step_removed;
+CREATE TABLE {{prefix}}_latency_info_flow_null_step_removed AS
+ SELECT
+ ROW_NUMBER() OVER (ORDER BY
+ curr.{{id_field}} ASC, curr.trace_id ASC, curr.ts ASC
+ ) AS row_number,
+ curr.id,
+ curr.ts,
+ curr.dur,
+ curr.track_id,
+ curr.trace_id,
+ curr.{{id_field}},
+ curr.gesture_slice_id,
+ curr.gesture_ts,
+ curr.{{prefix}}_dur,
+ curr.gesture_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.{{id_field}} != curr.{{id_field}} OR
+ prev.trace_id != curr.trace_id OR
+ prev.trace_id IS NULL OR
+ prev.step = 'AsyncBegin' THEN
+ 'Begin'
+ ELSE
+ CASE WHEN
+ next.{{id_field}} != curr.{{id_field}} 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
+ {{prefix}}_latency_info_flow_step_filtered curr LEFT JOIN
+ {{prefix}}_latency_info_flow_step_filtered prev ON
+ curr.row_number - 1 = prev.row_number LEFT JOIN
+ {{prefix}}_latency_info_flow_step_filtered next ON
+ curr.row_number + 1 = next.row_number
+ ORDER BY curr.{{id_field}} 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 {{prefix}}_flow_event;
+CREATE VIEW {{prefix}}_flow_event AS
+ SELECT
+ curr.trace_id,
+ curr.id,
+ curr.ts,
+ curr.dur,
+ curr.track_id,
+ curr.{{id_field}},
+ curr.gesture_slice_id AS {{prefix}}_slice_id,
+ curr.gesture_ts AS {{prefix}}_ts,
+ curr.{{prefix}}_dur AS {{prefix}}_dur,
+ curr.gesture_track_id AS {{prefix}}_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
+ {{prefix}}_latency_info_flow_null_step_removed curr LEFT JOIN
+ {{prefix}}_latency_info_flow_null_step_removed next ON
+ curr.row_number + 1 = next.row_number
+ ORDER BY curr.{{id_field}}, curr.trace_id, curr.ts;
diff --git a/src/trace_processor/metrics/chrome/gesture_flow_event_queuing_delay.sql b/src/trace_processor/metrics/chrome/gesture_flow_event_queuing_delay.sql
new file mode 100644
index 0000000..6701158
--- /dev/null
+++ b/src/trace_processor/metrics/chrome/gesture_flow_event_queuing_delay.sql
@@ -0,0 +1,75 @@
+--
+-- 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.
+--
+-- This metric takes each flow event in a InputLatency::{gesture_update} 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 {{prefix}}_flow_event table which gives us all the flow events
+-- with associated {gesture_update} events we care about and labels them
+-- janky or not.
+SELECT RUN_METRIC('chrome/{{prefix}}_flow_event.sql');
+
+-- Take each flow and next flow (from {{prefix}}_flow_event table) and generate
+-- the metric name as well as compute the time between.
+DROP VIEW IF EXISTS {{prefix}}_flow_event_queuing_delay;
+
+CREATE VIEW {{prefix}}_flow_event_queuing_delay AS
+ SELECT
+ trace_id,
+ id,
+ ts,
+ dur,
+ track_id,
+ {{id_field}},
+ {{prefix}}_slice_id,
+ {{prefix}}_ts,
+ {{prefix}}_dur,
+ {{prefix}}_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 {{prefix}}_flow_event
+ ORDER BY {{id_field}}, trace_id, ts;
diff --git a/src/trace_processor/metrics/chrome/gesture_jank.sql b/src/trace_processor/metrics/chrome/gesture_jank.sql
new file mode 100644
index 0000000..981e246
--- /dev/null
+++ b/src/trace_processor/metrics/chrome/gesture_jank.sql
@@ -0,0 +1,319 @@
+--
+-- 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.
+--
+-- A collection of templated metrics related to continuous motion gestures that
+-- have start, end and update events.
+--
+-- We define an update to be janky if comparing forwards or backwards (ignoring
+-- coalesced updates) a given updates 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 InputLatency 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.
+-- TODO(b/197841224): Refactor or remove this table.
+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 refreshing 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 "begin" and "end" events. We take their IDs to group them
+-- together into gestures later and the timestamp and duration to compute the
+-- duration of the gesture.
+DROP VIEW IF EXISTS {{prefix}}_begin_and_end;
+CREATE VIEW {{prefix}}_begin_and_end AS
+ SELECT
+ slice.name,
+ slice.id,
+ slice.ts,
+ slice.dur,
+ slice.track_id,
+ EXTRACT_ARG(arg_set_id, 'chrome_latency_info.{{id_field}}')
+ AS {{id_field}},
+ EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id
+ FROM
+ slice
+ WHERE
+ slice.name IN (
+ 'InputLatency::{{gesture_start}}',
+ 'InputLatency::{{gesture_end}}'
+ )
+ ORDER BY ts;
+
+-- Now we take the "begin" and the "end" events and join the information into a
+-- single row per gesture. We also compute the average Vysnc interval of the
+-- gesture (hopefully this would be either 60 FPS for the whole gesture 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_{{prefix}}_begin_and_end;
+CREATE VIEW joined_{{prefix}}_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.{{id_field}}, begin.trace_id)
+ AS begin_{{id_field}},
+ 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
+ ), 1e+9 / 60) AS avg_vsync_interval
+ FROM {{prefix}}_begin_and_end begin JOIN {{prefix}}_begin_and_end end ON
+ begin.trace_id < end.trace_id AND
+ begin.name = 'InputLatency::{{gesture_start}}' AND
+ end.name = 'InputLatency::{{gesture_end}}' AND (
+ (
+ begin.{{id_field}} IS NULL AND
+ end.trace_id = (
+ SELECT MIN(trace_id)
+ FROM {{prefix}}_begin_and_end in_query
+ WHERE
+ name = 'InputLatency::{{gesture_end}}' AND
+ in_query.trace_id > begin.trace_id
+ )
+ ) OR
+ end.{{id_field}} = begin.{{id_field}}
+ )
+ ORDER BY begin.ts;
+
+-- Get the "update" events by name ordered by the |{{id_field}}|, 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
+-- {{gesture_update}} event to the information about its "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 {{id_field}}_update;
+CREATE TABLE {{id_field}}_update AS
+ SELECT
+ ROW_NUMBER() OVER (
+ ORDER BY {{id_field}} ASC, ts ASC) AS row_number,
+ begin_id,
+ begin_ts,
+ begin_dur,
+ begin_track_id,
+ begin_trace_id,
+ COALESCE({{id_field}}, begin_trace_id) AS {{id_field}},
+ CASE WHEN
+ end_ts_and_dur > ts + dur THEN
+ end_ts_and_dur
+ ELSE
+ ts + dur
+ END AS maybe_gesture_end,
+ id,
+ ts,
+ dur,
+ track_id,
+ trace_id,
+ dur/avg_vsync_interval AS gesture_frames_exact
+ FROM joined_{{prefix}}_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.{{id_field}}')
+ AS {{id_field}},
+ *
+ FROM
+ slice JOIN track ON slice.track_id = track.id
+ WHERE
+ slice.name = 'InputLatency::{{gesture_update}}' AND
+ slice.dur != -1 AND
+ NOT COALESCE(
+ EXTRACT_ARG(arg_set_id, "chrome_latency_info.is_coalesced"),
+ TRUE)
+ AND slice.arg_set_id IN (
+ SELECT arg_set_id
+ FROM args
+ WHERE args.arg_set_id = slice.arg_set_id
+ AND flat_key = 'chrome_latency_info.component_info.component_type'
+ AND string_value = 'COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER'
+ )
+ ) gesture_update ON
+ gesture_update.ts <= begin_and_end.end_ts AND
+ gesture_update.ts >= begin_and_end.begin_ts AND
+ gesture_update.trace_id > begin_and_end.begin_trace_id AND
+ gesture_update.trace_id < begin_and_end.end_trace_id AND (
+ gesture_update.{{id_field}} IS NULL OR
+ gesture_update.{{id_field}} = begin_and_end.begin_{{id_field}}
+ );
+
+-- This takes the "update" events and joins it to the previous "update" event
+-- (previous row and NULL if there isn't one) and the next "update" 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 than 0.5 (which is
+-- 1/2 of 16 ms at 60 fps, and so on).
+--
+-- A small number is added to 0.5 in order to make sure that the comparison does
+-- not filter out ratios that are precisely 0.5, which can fall a little above
+-- or below exact value due to inherent inaccuracy of operations with
+-- floating-point numbers. Value 1e-9 have been chosen as follows: the ratio has
+-- nanoseconds in numerator and VSync interval in denominator. Assuming refresh
+-- rate more than 1 FPS (and therefore VSync interval less than a second), this
+-- ratio should increase with increments more than minimal value in numerator
+-- (1ns) divided by maximum value in denominator, giving 1e-9.
+--
+--
+-- We only compare an "update" event to another event within the same gesture
+-- ({{id_field}} == prev/next {{id_field}}). This controls somewhat for
+-- variability of gestures.
+--
+-- Note: Must be a TABLE because it uses a window function which can behave
+-- strangely in views.
+DROP TABLE IF EXISTS {{prefix}}_jank_maybe_null_prev_and_next;
+CREATE TABLE {{prefix}}_jank_maybe_null_prev_and_next AS
+ SELECT
+ currprev.*,
+ CASE WHEN
+ currprev.{{id_field}} != prev_{{id_field}} OR
+ prev_ts IS NULL OR
+ prev_ts < currprev.begin_ts OR
+ prev_ts > currprev.maybe_gesture_end
+ THEN
+ FALSE
+ ELSE
+ currprev.gesture_frames_exact > prev_gesture_frames_exact + 0.5 + 1e-9
+ END AS prev_jank,
+ CASE WHEN
+ currprev.{{id_field}} != next.{{id_field}} OR
+ next.ts IS NULL OR
+ next.ts < currprev.begin_ts OR
+ next.ts > currprev.maybe_gesture_end
+ THEN
+ FALSE
+ ELSE
+ currprev.gesture_frames_exact > next.gesture_frames_exact + 0.5 + 1e-9
+ END AS next_jank,
+ next.gesture_frames_exact AS next_gesture_frames_exact
+ FROM (
+ SELECT
+ curr.*,
+ curr.maybe_gesture_end - curr.begin_ts AS {{prefix}}_dur,
+ prev.ts AS prev_ts,
+ prev.{{id_field}} AS prev_{{id_field}},
+ prev.gesture_frames_exact AS prev_gesture_frames_exact
+ FROM
+ {{id_field}}_update curr LEFT JOIN
+ {{id_field}}_update prev ON prev.row_number + 1 = curr.row_number
+ ) currprev LEFT JOIN
+ {{id_field}}_update next ON currprev.row_number + 1 = next.row_number
+ ORDER BY currprev.{{id_field}} ASC, currprev.ts ASC;
+
+-- This just uses prev_jank and next_jank to see if each "update" event is a
+-- jank.
+DROP VIEW IF EXISTS {{prefix}}_jank;
+CREATE VIEW {{prefix}}_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 {{prefix}}_jank_maybe_null_prev_and_next
+ ORDER BY {{id_field}} ASC, ts ASC;
+
+DROP VIEW IF EXISTS {{prefix}}_jank_output;
+CREATE VIEW {{prefix}}_jank_output AS
+ SELECT
+ {{proto_name}}(
+ '{{prefix}}_jank_percentage', (
+ SELECT
+ (
+ SUM(CASE WHEN jank THEN dur ELSE 0 END)/CAST(SUM(dur) AS REAL)
+ ) * 100.0
+ FROM {{prefix}}_jank
+ ),
+ '{{prefix}}_ms', (
+ SELECT
+ CAST(SUM({{prefix}}_dur)/1e6 AS REAL)
+ FROM (
+ SELECT
+ MAX({{prefix}}_dur) AS {{prefix}}_dur
+ FROM {{prefix}}_jank
+ GROUP BY {{id_field}}
+ )
+ ),
+ '{{prefix}}_processing_ms', CAST(SUM(dur)/1e6 AS REAL),
+ '{{prefix}}_jank_processing_ms', (
+ SELECT CAST(SUM(dur)/1e6 AS REAL) FROM {{prefix}}_jank WHERE jank
+ ),
+ 'num_{{prefix}}_update_count', COUNT(*),
+ 'num_{{prefix}}_update_jank_count', SUM(jank)
+ )
+ FROM {{prefix}}_jank;
diff --git a/src/trace_processor/metrics/chrome/scroll_flow_event.sql b/src/trace_processor/metrics/chrome/scroll_flow_event.sql
index 05699f4..083c35d 100644
--- a/src/trace_processor/metrics/chrome/scroll_flow_event.sql
+++ b/src/trace_processor/metrics/chrome/scroll_flow_event.sql
@@ -23,236 +23,9 @@
-- 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;
+SELECT RUN_METRIC(
+ 'chrome/gesture_flow_event.sql',
+ 'prefix', 'scroll',
+ 'gesture_update', 'GestureScrollUpdate',
+ 'id_field', 'gesture_scroll_id'
+ );
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
index 81eba40..94a8f48 100644
--- a/src/trace_processor/metrics/chrome/scroll_flow_event_queuing_delay.sql
+++ b/src/trace_processor/metrics/chrome/scroll_flow_event_queuing_delay.sql
@@ -21,55 +21,7 @@
-- 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');
+SELECT RUN_METRIC('chrome/gesture_flow_event_queuing_delay.sql',
+ 'prefix', 'scroll',
+ 'id_field', 'gesture_scroll_id');
--- 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
index 0564bd5..984a6c7 100644
--- a/src/trace_processor/metrics/chrome/scroll_jank.sql
+++ b/src/trace_processor/metrics/chrome/scroll_jank.sql
@@ -24,280 +24,15 @@
-- 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');
+SELECT RUN_METRIC(
+ 'chrome/gesture_jank.sql',
+ 'prefix', 'scroll',
+ 'gesture_start', 'GestureScrollBegin',
+ 'gesture_update', 'GestureScrollUpdate',
+ 'gesture_end', 'GestureScrollEnd',
+ 'id_field', 'gesture_scroll_id',
+ 'proto_name', 'ScrollJank');
--- 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;
+-- TODO(b/200149773): Remove this once chrometto no longer depends on it.
+DROP VIEW IF EXISTS gesture_scroll_update;
+CREATE VIEW gesture_scroll_update AS SELECT * FROM gesture_scroll_id_update;
diff --git a/src/trace_processor/metrics/chrome/touch_flow_event.sql b/src/trace_processor/metrics/chrome/touch_flow_event.sql
new file mode 100644
index 0000000..3318ff7
--- /dev/null
+++ b/src/trace_processor/metrics/chrome/touch_flow_event.sql
@@ -0,0 +1,31 @@
+--
+-- 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.
+--
+-- While handling a InputLatency::TouchMove event a sequence of Flows define the
+-- critical path from Beginning to End. This metric breaks down the flows for
+-- the same InputLatency::TouchMove 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 touch_jank table which gives us all the TouchMove events we care
+-- about and labels them janky or not.
+SELECT RUN_METRIC(
+ 'chrome/gesture_flow_event.sql',
+ 'prefix', 'touch',
+ 'gesture_update', 'TouchMove',
+ 'id_field', 'touch_id'
+ );
diff --git a/src/trace_processor/metrics/chrome/touch_flow_event_queuing_delay.sql b/src/trace_processor/metrics/chrome/touch_flow_event_queuing_delay.sql
new file mode 100644
index 0000000..2c493d1
--- /dev/null
+++ b/src/trace_processor/metrics/chrome/touch_flow_event_queuing_delay.sql
@@ -0,0 +1,26 @@
+--
+-- 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.
+--
+-- 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 TouchMove events we care about and labels them janky or not.
+SELECT RUN_METRIC('chrome/gesture_flow_event_queuing_delay.sql',
+ 'prefix', 'touch',
+ 'id_field', 'touch_id');
+
diff --git a/src/trace_processor/metrics/chrome/touch_jank.sql b/src/trace_processor/metrics/chrome/touch_jank.sql
new file mode 100644
index 0000000..2920099
--- /dev/null
+++ b/src/trace_processor/metrics/chrome/touch_jank.sql
@@ -0,0 +1,33 @@
+--
+-- 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.
+--
+-- A collection of metrics related to TouchMove events.
+--
+-- We define a TouchMove to be janky if comparing forwards or backwards
+-- (ignoring coalesced updates) a given TouchMove 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.
+
+SELECT RUN_METRIC(
+ 'chrome/gesture_jank.sql',
+ 'prefix', 'touch',
+ 'gesture_start', 'TouchStart',
+ 'gesture_update', 'TouchMove',
+ 'gesture_end', 'TouchEnd',
+ 'id_field', 'touch_id',
+ 'proto_name', 'TouchJank');
diff --git a/src/trace_processor/metrics/metrics.cc b/src/trace_processor/metrics/metrics.cc
index 4f34d3c..6c09c58 100644
--- a/src/trace_processor/metrics/metrics.cc
+++ b/src/trace_processor/metrics/metrics.cc
@@ -36,14 +36,6 @@
namespace {
-// TODO(lalitm): delete this and use sqlite_utils when that is cleaned up of
-// trace processor dependencies.
-const char* ExtractSqliteValue(sqlite3_value* value) {
- auto type = sqlite3_value_type(value);
- PERFETTO_DCHECK(type == SQLITE_TEXT);
- return reinterpret_cast<const char*>(sqlite3_value_text(value));
-}
-
SqlValue SqlValueFromSqliteValue(sqlite3_value* value) {
SqlValue sql_value;
switch (sqlite3_value_type(value)) {
@@ -69,13 +61,76 @@
return sql_value;
}
+base::Optional<std::string> SqlValueToString(SqlValue value) {
+ switch (value.type) {
+ case SqlValue::Type::kString:
+ return value.AsString();
+ case SqlValue::Type::kDouble:
+ return std::to_string(value.AsDouble());
+ case SqlValue::Type::kLong:
+ return std::to_string(value.AsLong());
+ case SqlValue::Type::kBytes:
+ case SqlValue::Type::kNull:
+ return base::nullopt;
+ }
+ PERFETTO_FATAL("For GCC");
+}
+
+base::Status ValidateSingleNonEmptyMessage(const uint8_t* ptr,
+ size_t size,
+ uint32_t schema_type,
+ const std::string& message_type,
+ protozero::ConstBytes* out) {
+ PERFETTO_DCHECK(size > 0);
+
+ if (size > protozero::proto_utils::kMaxMessageLength) {
+ return base::ErrStatus(
+ "Message has size %zu which is larger than the maximum allowed message "
+ "size %zu",
+ size, protozero::proto_utils::kMaxMessageLength);
+ }
+
+ protos::pbzero::ProtoBuilderResult::Decoder decoder(ptr, size);
+ if (decoder.is_repeated()) {
+ return base::ErrStatus("Cannot handle nested repeated messages");
+ }
+
+ const auto& single_field = decoder.single();
+ protos::pbzero::SingleBuilderResult::Decoder single(single_field.data,
+ single_field.size);
+
+ if (single.type() != schema_type) {
+ return base::ErrStatus("Message field has wrong wire type %d",
+ single.type());
+ }
+
+ base::StringView actual_type(single.type_name());
+ if (actual_type != base::StringView(message_type)) {
+ return base::ErrStatus("Field has wrong type (expected %s, was %s)",
+ message_type.c_str(),
+ actual_type.ToStdString().c_str());
+ }
+
+ if (!single.has_protobuf()) {
+ return base::ErrStatus("Message has no proto bytes");
+ }
+
+ // We disallow 0 size fields here as they should have been reported as null
+ // one layer down.
+ *out = single.protobuf();
+ if (out->size == 0) {
+ return base::ErrStatus("Field has zero size");
+ }
+ return base::OkStatus();
+}
+
} // namespace
ProtoBuilder::ProtoBuilder(const DescriptorPool* pool,
const ProtoDescriptor* descriptor)
: pool_(pool), descriptor_(descriptor) {}
-util::Status ProtoBuilder::AppendSqlValue(const std::string& field_name,
+base::Status ProtoBuilder::AppendSqlValue(const std::string& field_name,
const SqlValue& value) {
switch (value.type) {
case SqlValue::kLong:
@@ -91,24 +146,24 @@
case SqlValue::kNull:
// If the value is null, it's treated as the field being absent so we
// don't append anything.
- return util::OkStatus();
+ return base::OkStatus();
}
PERFETTO_FATAL("For GCC");
}
-util::Status ProtoBuilder::AppendLong(const std::string& field_name,
+base::Status ProtoBuilder::AppendLong(const std::string& field_name,
int64_t value,
bool is_inside_repeated) {
auto field = descriptor_->FindFieldByName(field_name);
if (!field) {
- return util::ErrStatus("Field with name %s not found in proto type %s",
+ return base::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 util::ErrStatus(
+ return base::ErrStatus(
"Unexpected long value for repeated field %s in proto type %s",
field_name.c_str(), descriptor_->full_name().c_str());
}
@@ -124,7 +179,7 @@
auto opt_enum_descriptor_idx =
pool_->FindDescriptorIdx(field->resolved_type_name());
if (!opt_enum_descriptor_idx) {
- return util::ErrStatus(
+ return base::ErrStatus(
"Unable to find enum type %s to fill field %s (in proto message "
"%s)",
field->resolved_type_name().c_str(), field->name().c_str(),
@@ -133,7 +188,7 @@
const auto& enum_desc = pool_->descriptors()[*opt_enum_descriptor_idx];
auto opt_enum_str = enum_desc.FindEnumString(static_cast<int32_t>(value));
if (!opt_enum_str) {
- return util::ErrStatus("Invalid enum value %" PRId64
+ return base::ErrStatus("Invalid enum value %" PRId64
" "
"in enum type %s; encountered while filling "
"field %s (in proto message %s)",
@@ -155,35 +210,35 @@
message_->AppendFixed(field->number(), value);
break;
case FieldDescriptorProto::TYPE_UINT64:
- return util::ErrStatus(
+ return base::ErrStatus(
"Field %s (in proto message %s) is using a uint64 type. uint64 in "
"metric messages is not supported by trace processor; use an int64 "
"field instead.",
field->name().c_str(), descriptor_->full_name().c_str());
default: {
- return util::ErrStatus(
+ return base::ErrStatus(
"Tried to write value of type long into field %s (in proto type %s) "
"which has type %d",
field->name().c_str(), descriptor_->full_name().c_str(),
field->type());
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
-util::Status ProtoBuilder::AppendDouble(const std::string& field_name,
+base::Status ProtoBuilder::AppendDouble(const std::string& field_name,
double value,
bool is_inside_repeated) {
auto field = descriptor_->FindFieldByName(field_name);
if (!field) {
- return util::ErrStatus("Field with name %s not found in proto type %s",
+ return base::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 util::ErrStatus(
+ return base::ErrStatus(
"Unexpected double value for repeated field %s in proto type %s",
field_name.c_str(), descriptor_->full_name().c_str());
}
@@ -199,29 +254,29 @@
break;
}
default: {
- return util::ErrStatus(
+ return base::ErrStatus(
"Tried to write value of type double into field %s (in proto type "
"%s) which has type %d",
field->name().c_str(), descriptor_->full_name().c_str(),
field->type());
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
-util::Status ProtoBuilder::AppendString(const std::string& field_name,
+base::Status ProtoBuilder::AppendString(const std::string& field_name,
base::StringView data,
bool is_inside_repeated) {
const FieldDescriptor* field = descriptor_->FindFieldByName(field_name);
if (!field) {
- return util::ErrStatus("Field with name %s not found in proto type %s",
+ return base::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 util::ErrStatus(
+ return base::ErrStatus(
"Unexpected string value for repeated field %s in proto type %s",
field_name.c_str(), descriptor_->full_name().c_str());
}
@@ -235,7 +290,7 @@
auto opt_enum_descriptor_idx =
pool_->FindDescriptorIdx(field->resolved_type_name());
if (!opt_enum_descriptor_idx) {
- return util::ErrStatus(
+ return base::ErrStatus(
"Unable to find enum type %s to fill field %s (in proto message "
"%s)",
field->resolved_type_name().c_str(), field->name().c_str(),
@@ -245,7 +300,7 @@
std::string enum_str = data.ToStdString();
auto opt_enum_value = enum_desc.FindEnumValue(enum_str);
if (!opt_enum_value) {
- return util::ErrStatus(
+ return base::ErrStatus(
"Invalid enum string %s "
"in enum type %s; encountered while filling "
"field %s (in proto message %s)",
@@ -256,23 +311,23 @@
break;
}
default: {
- return util::ErrStatus(
+ return base::ErrStatus(
"Tried to write value of type string into field %s (in proto type "
"%s) which has type %d",
field->name().c_str(), descriptor_->full_name().c_str(),
field->type());
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
-util::Status ProtoBuilder::AppendBytes(const std::string& field_name,
+base::Status ProtoBuilder::AppendBytes(const std::string& field_name,
const uint8_t* ptr,
size_t size,
bool is_inside_repeated) {
const FieldDescriptor* field = descriptor_->FindFieldByName(field_name);
if (!field) {
- return util::ErrStatus("Field with name %s not found in proto type %s",
+ return base::ErrStatus("Field with name %s not found in proto type %s",
field_name.c_str(),
descriptor_->full_name().c_str());
}
@@ -285,7 +340,7 @@
return AppendSingleMessage(*field, ptr, size);
if (size == 0) {
- return util::ErrStatus(
+ return base::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 "
@@ -293,13 +348,13 @@
field->name().c_str(), descriptor_->full_name().c_str());
}
- return util::ErrStatus(
+ return base::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());
}
-util::Status ProtoBuilder::AppendSingleMessage(const FieldDescriptor& field,
+base::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
@@ -309,60 +364,26 @@
// just pass an empty string (which will have a valid pointer always) and
// zero as the size.
message_->AppendBytes(field.number(), "", 0);
- return util::OkStatus();
+ return base::OkStatus();
}
- if (size > protozero::proto_utils::kMaxMessageLength) {
- return util::ErrStatus(
- "Message passed to field %s in proto message %s has size %zu which is "
- "larger than the maximum allowed message size %zu",
- field.name().c_str(), descriptor_->full_name().c_str(), size,
- protozero::proto_utils::kMaxMessageLength);
+ protozero::ConstBytes bytes;
+ base::Status validation = ValidateSingleNonEmptyMessage(
+ ptr, size, field.type(), field.resolved_type_name(), &bytes);
+ if (!validation.ok()) {
+ return util::ErrStatus("[Field %s in message %s]: %s", field.name().c_str(),
+ descriptor_->full_name().c_str(),
+ validation.c_message());
}
-
- protos::pbzero::ProtoBuilderResult::Decoder decoder(ptr, size);
- if (decoder.is_repeated()) {
- return util::ErrStatus("Cannot handle nested repeated messages in field %s",
- field.name().c_str());
- }
-
- const auto& single_field = decoder.single();
- protos::pbzero::SingleBuilderResult::Decoder single(single_field.data,
- single_field.size);
-
- if (single.type() != field.type()) {
- return util::ErrStatus("Field %s has wrong type (expected %u, was %u)",
- field.name().c_str(), field.type(), single.type());
- }
-
- auto actual_type_name = single.type_name().ToStdString();
- if (actual_type_name != field.resolved_type_name()) {
- return util::ErrStatus("Field %s has wrong type (expected %s, was %s)",
- field.name().c_str(), actual_type_name.c_str(),
- field.resolved_type_name().c_str());
- }
-
- if (!single.has_protobuf()) {
- return util::ErrStatus("Field %s has no proto bytes", field.name().c_str());
- }
-
- // We disallow 0 size fields here as they should have been reported as null
- // one layer down.
- auto bytes = single.protobuf();
- if (bytes.size == 0) {
- return util::ErrStatus("Unexpected to see field %s with zero size",
- field.name().c_str());
- }
-
message_->AppendBytes(field.number(), bytes.data, bytes.size);
- return util::OkStatus();
+ return base::OkStatus();
}
-util::Status ProtoBuilder::AppendRepeated(const FieldDescriptor& field,
+base::Status ProtoBuilder::AppendRepeated(const FieldDescriptor& field,
const uint8_t* ptr,
size_t size) {
if (size > protozero::proto_utils::kMaxMessageLength) {
- return util::ErrStatus(
+ return base::ErrStatus(
"Message passed to field %s in proto message %s has size %zu which is "
"larger than the maximum allowed message size %zu",
field.name().c_str(), descriptor_->full_name().c_str(), size,
@@ -371,7 +392,7 @@
protos::pbzero::ProtoBuilderResult::Decoder decoder(ptr, size);
if (!decoder.is_repeated()) {
- return util::ErrStatus(
+ return base::ErrStatus(
"Unexpected message value for repeated field %s in proto type %s",
field.name().c_str(), descriptor_->full_name().c_str());
}
@@ -381,7 +402,7 @@
for (auto it = repeated.value(); it; ++it) {
protos::pbzero::RepeatedBuilderResult::Value::Decoder value(*it);
- util::Status status;
+ base::Status status;
if (value.has_int_value()) {
status = AppendLong(field.name(), value.int_value(), true);
} else if (value.has_double_value()) {
@@ -393,13 +414,13 @@
const auto& bytes = value.bytes_value();
status = AppendBytes(field.name(), bytes.data, bytes.size, true);
} else {
- status = util::ErrStatus("Unknown type in repeated field");
+ status = base::ErrStatus("Unknown type in repeated field");
}
if (!status.ok())
return status;
}
- return util::OkStatus();
+ return base::OkStatus();
}
std::vector<uint8_t> ProtoBuilder::SerializeToProtoBuilderResult() {
@@ -427,7 +448,7 @@
repeated_ = message_->set_repeated();
}
-util::Status RepeatedFieldBuilder::AddSqlValue(SqlValue value) {
+base::Status RepeatedFieldBuilder::AddSqlValue(SqlValue value) {
switch (value.type) {
case SqlValue::kLong:
AddLong(value.long_value);
@@ -446,7 +467,7 @@
AddBytes(nullptr, 0);
break;
}
- return util::OkStatus();
+ return base::OkStatus();
}
void RepeatedFieldBuilder::AddLong(int64_t value) {
@@ -587,8 +608,8 @@
const auto* fn_ctx =
static_cast<const BuildProtoContext*>(sqlite3_user_data(ctx));
if (argc % 2 != 0) {
- util::Status error =
- util::ErrStatus("Invalid number of args to %s BuildProto (got %d)",
+ base::Status error =
+ base::ErrStatus("Invalid number of args to %s BuildProto (got %d)",
fn_ctx->desc->full_name().c_str(), argc);
sqlite3_result_error(ctx, error.c_message(), -1);
return;
@@ -646,13 +667,21 @@
std::unordered_map<std::string, std::string> substitutions;
for (int i = 1; i < argc; i += 2) {
if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) {
- sqlite3_result_error(ctx, "RUN_METRIC: Invalid args", -1);
+ sqlite3_result_error(ctx, "RUN_METRIC: all keys must be strings", -1);
return;
}
- auto* key_str = ExtractSqliteValue(argv[i]);
- auto* value_str = ExtractSqliteValue(argv[i + 1]);
- substitutions[key_str] = value_str;
+ base::Optional<std::string> key_str =
+ SqlValueToString(SqlValueFromSqliteValue(argv[i]));
+ base::Optional<std::string> value_str =
+ SqlValueToString(SqlValueFromSqliteValue(argv[i + 1]));
+
+ if (!value_str) {
+ sqlite3_result_error(
+ ctx, "RUN_METRIC: all values must be convertible to strings", -1);
+ return;
+ }
+ substitutions[*key_str] = *value_str;
}
for (const auto& query : base::SplitString(sql, ";\n")) {
@@ -669,7 +698,7 @@
auto it = fn_ctx->tp->ExecuteQuery(buffer);
it.Next();
- util::Status status = it.Status();
+ base::Status status = it.Status();
if (!status.ok()) {
char* error =
sqlite3_mprintf("RUN_METRIC: Error when running file %s: %s", path,
@@ -682,7 +711,55 @@
sqlite3_result_null(ctx);
}
-util::Status ComputeMetrics(TraceProcessor* tp,
+void UnwrapMetricProto(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
+ if (argc != 2) {
+ sqlite3_result_error(ctx,
+ "UNWRAP_METRIC_PROTO: Expected exactly proto and "
+ "message type as arguments",
+ -1);
+ return;
+ }
+
+ SqlValue proto = SqlValueFromSqliteValue(argv[0]);
+ SqlValue message_type = SqlValueFromSqliteValue(argv[1]);
+
+ if (proto.type != SqlValue::Type::kBytes) {
+ sqlite3_result_error(ctx, "UNWRAP_METRIC_PROTO: proto is not a blob", -1);
+ return;
+ }
+
+ if (message_type.type != SqlValue::Type::kString) {
+ sqlite3_result_error(ctx, "UNWRAP_METRIC_PROTO: message type is not string",
+ -1);
+ return;
+ }
+
+ const uint8_t* ptr = static_cast<const uint8_t*>(proto.AsBytes());
+ size_t size = proto.bytes_count;
+ if (size == 0) {
+ sqlite3_result_blob(ctx, "", 0, nullptr);
+ return;
+ }
+
+ static constexpr uint32_t kMessageType =
+ static_cast<uint32_t>(protozero::proto_utils::ProtoSchemaType::kMessage);
+ protozero::ConstBytes bytes;
+ base::Status validation = ValidateSingleNonEmptyMessage(
+ ptr, size, kMessageType, message_type.AsString(), &bytes);
+ if (!validation.ok()) {
+ base::Status res =
+ util::ErrStatus("UNWRAP_METRICS_PROTO: %s", validation.c_message());
+ sqlite3_result_error(ctx, res.c_message(), -1);
+ return;
+ }
+
+ std::unique_ptr<uint8_t[], base::FreeDeleter> data(
+ static_cast<uint8_t*>(malloc(bytes.size)));
+ memcpy(data.get(), bytes.data, bytes.size);
+ sqlite3_result_blob(ctx, data.release(), static_cast<int>(bytes.size), free);
+}
+
+base::Status ComputeMetrics(TraceProcessor* tp,
const std::vector<std::string> metrics_to_compute,
const std::vector<SqlMetricFile>& sql_metrics,
const DescriptorPool& pool,
@@ -697,7 +774,7 @@
name == metric.proto_field_name.value();
});
if (metric_it == sql_metrics.end())
- return util::ErrStatus("Unknown metric %s", name.c_str());
+ return base::ErrStatus("Unknown metric %s", name.c_str());
const auto& sql_metric = *metric_it;
auto queries = base::SplitString(sql_metric.sql, ";\n");
@@ -728,27 +805,27 @@
}
if (it.ColumnCount() != 1) {
- return util::ErrStatus("Output table %s should have exactly one column",
+ return base::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) {
- return util::ErrStatus("Output table %s column has invalid type",
+ return base::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",
+ return base::ErrStatus("Output table %s should have at most one row",
sql_metric.output_table_name.value().c_str());
}
RETURN_IF_ERROR(it.Status());
}
*metrics_proto = metric_builder.SerializeRaw();
- return util::OkStatus();
+ return base::OkStatus();
}
} // namespace metrics
diff --git a/src/trace_processor/metrics/metrics.h b/src/trace_processor/metrics/metrics.h
index b999225..c6cdb35 100644
--- a/src/trace_processor/metrics/metrics.h
+++ b/src/trace_processor/metrics/metrics.h
@@ -63,22 +63,22 @@
public:
ProtoBuilder(const DescriptorPool*, const ProtoDescriptor*);
- util::Status AppendSqlValue(const std::string& field_name,
+ base::Status AppendSqlValue(const std::string& field_name,
const SqlValue& value);
// Note: all external callers to these functions should not
// |is_inside_repeated| to this function and instead rely on the default
// value.
- util::Status AppendLong(const std::string& field_name,
+ base::Status AppendLong(const std::string& field_name,
int64_t value,
bool is_inside_repeated = false);
- util::Status AppendDouble(const std::string& field_name,
+ base::Status AppendDouble(const std::string& field_name,
double value,
bool is_inside_repeated = false);
- util::Status AppendString(const std::string& field_name,
+ base::Status AppendString(const std::string& field_name,
base::StringView value,
bool is_inside_repeated = false);
- util::Status AppendBytes(const std::string& field_name,
+ base::Status AppendBytes(const std::string& field_name,
const uint8_t* data,
size_t size,
bool is_inside_repeated = false);
@@ -98,11 +98,11 @@
std::vector<uint8_t> SerializeRaw();
private:
- util::Status AppendSingleMessage(const FieldDescriptor& field,
+ base::Status AppendSingleMessage(const FieldDescriptor& field,
const uint8_t* ptr,
size_t size);
- util::Status AppendRepeated(const FieldDescriptor& field,
+ base::Status AppendRepeated(const FieldDescriptor& field,
const uint8_t* ptr,
size_t size);
@@ -118,7 +118,7 @@
public:
RepeatedFieldBuilder();
- util::Status AddSqlValue(SqlValue value);
+ base::Status AddSqlValue(SqlValue value);
void AddLong(int64_t value);
void AddDouble(double value);
@@ -171,10 +171,13 @@
std::vector<SqlMetricFile>* metrics;
};
-// This function implements the RUN_METRIC SQL function.
+// Implements the RUN_METRIC SQL function.
void RunMetric(sqlite3_context* ctx, int argc, sqlite3_value** argv);
-util::Status ComputeMetrics(TraceProcessor* impl,
+// Implements the UNWRAP_METRIC_PROTO SQL function.
+void UnwrapMetricProto(sqlite3_context* ctx, int argc, sqlite3_value** argv);
+
+base::Status ComputeMetrics(TraceProcessor* impl,
const std::vector<std::string> metrics_to_compute,
const std::vector<SqlMetricFile>& metrics,
const DescriptorPool& pool,
diff --git a/src/trace_processor/metrics/trace_metadata.sql b/src/trace_processor/metrics/trace_metadata.sql
index 838116b..7a91ed1 100644
--- a/src/trace_processor/metrics/trace_metadata.sql
+++ b/src/trace_processor/metrics/trace_metadata.sql
@@ -14,6 +14,18 @@
-- limitations under the License.
--
+-- Expose all clock snapshots as instant events.
+DROP VIEW IF EXISTS trace_metadata_event;
+CREATE VIEW trace_metadata_event AS
+SELECT
+ 'slice' as track_type,
+ 'Clock Snapshots' as track_name,
+ ts,
+ 0 as dur,
+ 'Snapshot' as slice_name
+FROM clock_snapshot
+GROUP BY ts;
+
DROP VIEW IF EXISTS trace_metadata_output;
CREATE VIEW trace_metadata_output AS
SELECT TraceMetadata(
diff --git a/src/trace_processor/metrics/webview/webview_power_usage.sql b/src/trace_processor/metrics/webview/webview_power_usage.sql
index 7ac8efc..96104fc 100644
--- a/src/trace_processor/metrics/webview/webview_power_usage.sql
+++ b/src/trace_processor/metrics/webview/webview_power_usage.sql
@@ -22,26 +22,26 @@
SELECT RUN_METRIC('android/android_proxy_power.sql');
SELECT RUN_METRIC('android/cpu_info.sql');
-DROP VIEW IF EXISTS top_level_slice;
+DROP TABLE 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
+CREATE TABLE 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;
+DROP TABLE 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
+CREATE TABLE webview_browser_slices AS
SELECT
top_level_slice.ts,
top_level_slice.dur,
@@ -66,21 +66,21 @@
USING SPAN_JOIN(power_per_thread PARTITIONED utid,
webview_browser_slices PARTITIONED utid);
-DROP VIEW IF EXISTS webview_browser_slices_power_summary;
+DROP TABLE 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
+CREATE TABLE 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;
+DROP TABLE IF EXISTS webview_renderer_threads;
-- All threads of all WebView renderer processes.
-CREATE VIEW webview_renderer_threads AS
+CREATE TABLE webview_renderer_threads AS
SELECT
thread.utid AS utid,
extract_arg(process.arg_set_id, 'chrome.host_app_package_name') as app_name
@@ -90,11 +90,11 @@
WHERE process.name LIKE '%webview%SandboxedProcessService%'
AND app_name IS NOT NULL;
-DROP VIEW IF EXISTS webview_renderer_power_summary;
+DROP TABLE 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
+CREATE TABLE webview_renderer_power_summary AS
SELECT
app_name,
SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
@@ -103,11 +103,11 @@
ON power_per_thread.utid = webview_renderer_threads.utid
GROUP BY app_name;
-DROP VIEW IF EXISTS webview_renderer_power_per_core_type;
+DROP TABLE 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
+CREATE TABLE webview_renderer_power_per_core_type AS
SELECT
app_name,
core_type_per_cpu.core_type AS core_type,
@@ -119,7 +119,7 @@
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;
+DROP TABLE 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;
@@ -127,7 +127,7 @@
-- 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
+CREATE TABLE host_app_threads AS
SELECT
thread.utid AS utid,
thread.name AS name,
@@ -140,11 +140,11 @@
AND process.name NOT LIKE '%chrome%'
AND app_name IS NOT NULL;
-DROP VIEW IF EXISTS host_app_power_summary;
+DROP TABLE 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
+CREATE TABLE host_app_power_summary AS
SELECT
app_name,
SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
@@ -153,11 +153,11 @@
ON power_per_thread.utid = host_app_threads.utid
GROUP BY app_name;
-DROP VIEW IF EXISTS host_app_power_per_core_type;
+DROP TABLE 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
+CREATE TABLE host_app_power_per_core_type AS
SELECT
app_name,
core_type_per_cpu.core_type AS core_type,
@@ -169,10 +169,10 @@
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;
+DROP TABLE IF EXISTS webview_only_threads;
-- A subset of the host app threads that are WebView-specific.
-CREATE VIEW webview_only_threads AS
+CREATE TABLE webview_only_threads AS
SELECT *
FROM host_app_threads
WHERE name LIKE 'Chrome%' OR name LIKE 'CookieMonster%'
@@ -181,11 +181,11 @@
OR name IN ('AudioThread', 'DedicatedWorker thread', 'GpuMemoryThread',
'JavaBridge', 'LevelDBEnv.IDB', 'MemoryInfra', 'NetworkService', 'VizWebView');
-DROP VIEW IF EXISTS webview_only_power_summary;
+DROP TABLE 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
+CREATE TABLE webview_only_power_summary AS
SELECT
app_name,
SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
@@ -194,11 +194,11 @@
ON power_per_thread.utid = webview_only_threads.utid
GROUP BY app_name;
-DROP VIEW IF EXISTS webview_only_power_per_core_type;
+DROP TABLE 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
+CREATE TABLE 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
@@ -211,9 +211,9 @@
-- Create views for output.
-DROP VIEW IF EXISTS total_app_power_output;
+DROP TABLE IF EXISTS total_app_power_output;
-CREATE VIEW total_app_power_output AS
+CREATE TABLE total_app_power_output AS
SELECT
host_app_power_summary.app_name as app_name,
host_app_power_summary.power_mas AS total_mas,
@@ -230,9 +230,9 @@
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;
+DROP TABLE IF EXISTS webview_renderer_power_output;
-CREATE VIEW webview_renderer_power_output AS
+CREATE TABLE webview_renderer_power_output AS
SELECT
webview_renderer_power_summary.app_name AS app_name,
webview_renderer_power_summary.power_mas AS total_mas,
@@ -249,9 +249,9 @@
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;
+DROP TABLE IF EXISTS webview_only_power_output;
-CREATE VIEW webview_only_power_output AS
+CREATE TABLE webview_only_power_output AS
SELECT
webview_only_power_summary.app_name AS app_name,
webview_only_power_summary.power_mas AS total_mas,
@@ -268,11 +268,9 @@
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;
+DROP TABLE IF EXISTS total_device_power;
-- Calculate the power usage of the device in milliampere-seconds.
-CREATE VIEW total_device_power AS
+CREATE TABLE 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/perfetto/trace_processor/api.py b/src/trace_processor/python/perfetto/trace_processor/api.py
index 9cabf07..8a31b81 100644
--- a/src/trace_processor/python/perfetto/trace_processor/api.py
+++ b/src/trace_processor/python/perfetto/trace_processor/api.py
@@ -32,8 +32,7 @@
# 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_INVALID_FIELD_ID = 0
QUERY_CELL_NULL_FIELD_ID = 1
QUERY_CELL_VARINT_FIELD_ID = 2
QUERY_CELL_FLOAT64_FIELD_ID = 3
@@ -55,28 +54,55 @@
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
+ self.__column_count = 0
+ self.__count = 0
+ self.__cells = []
+ self.__data_lists = [[], [], [], [], [], []]
+ self.__data_lists_index = [0, 0, 0, 0, 0, 0]
+ self.__current_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')
+ # Iterate over all the batches and collect their
+ # contents into lists based on the type of the batch
+ batch_index = 0
+ while True:
+ # Null-terminated strings in a batch are concatenated
+ # into a single large byte array, so we split on the
+ # null-terminator to get the individual strings
+ strings_batch = batches[batch_index].string_cells.split('\0')[:-1]
+ self.__data_lists[TraceProcessor.QUERY_CELL_STRING_FIELD_ID].extend(
+ strings_batch)
+ self.__data_lists[TraceProcessor.QUERY_CELL_VARINT_FIELD_ID].extend(
+ batches[batch_index].varint_cells)
+ self.__data_lists[TraceProcessor.QUERY_CELL_FLOAT64_FIELD_ID].extend(
+ batches[batch_index].float64_cells)
+ self.__data_lists[TraceProcessor.QUERY_CELL_BLOB_FIELD_ID].extend(
+ batches[batch_index].blob_cells)
+ self.__cells.extend(batches[batch_index].cells)
- def cells(self):
- return self.__batches[self.__batch_index].cells
+ if batches[batch_index].is_last_batch:
+ break
+ batch_index += 1
+
+ # If there are no rows in the query result, exit since
+ # we won't be returning anything and don't need to go
+ # through the process of generating the mapping between
+ # columns and data_list indices
+ if len(self.__cells) == 0:
+ return
+
+ # The count we collected so far was a count of all individual columns
+ # in the query result, so we divide by the number of columns in a row
+ # to get the number of rows
+ self.__column_count = len(self.__column_names)
+ self.__count = int(len(self.__cells) / self.__column_count)
+
+ # Data integrity check - see that we have the expected amount of cells
+ # for the number of rows that we need to return
+ if len(self.__cells) % self.__column_count != 0:
+ raise TraceProcessorException("Cell count " + str(len(self.__cells)) +
+ " is not a multiple of column count " +
+ str(len(self.__column_names)))
# To use the query result as a populated Pandas dataframe, this
# function must be called directly after calling query inside
@@ -89,91 +115,67 @@
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
-
+ for i in range(0, self.__count):
row = []
+ base_cell_index = i * self.__column_count
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
+ col_type = self.__cells[base_cell_index + num]
+ if col_type == TraceProcessor.QUERY_CELL_INVALID_FIELD_ID:
+ raise TraceProcessorException('Invalid cell type')
+ elif col_type != TraceProcessor.QUERY_CELL_NULL_FIELD_ID:
+ col_index = self.__data_lists_index[col_type]
+ self.__data_lists_index[col_type] += 1
+ row.append(self.__data_lists[col_type][col_index])
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))
+ row.append(None)
+
df.loc[-1] = row
df.index = df.index + 1
- self.__next_index = self.__next_index + len(self.__column_names)
+ ordered_df = df.reset_index(drop=True)
+ return ordered_df
except ModuleNotFoundError:
raise TraceProcessorException(
'The sufficient libraries are not installed')
+ def __len__(self):
+ return self.__count
+
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()
+ if self.__current_index == self.__count:
+ raise StopIteration
+ result = TraceProcessor.Row()
+ base_cell_index = self.__current_index * self.__column_count
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
+ col_type = self.__cells[base_cell_index + num]
+ if col_type == TraceProcessor.QUERY_CELL_INVALID_FIELD_ID:
+ raise TraceProcessorException('Invalid cell type')
+ if col_type != TraceProcessor.QUERY_CELL_NULL_FIELD_ID:
+ col_index = self.__data_lists_index[col_type]
+ self.__data_lists_index[col_type] += 1
+ setattr(result, column_name, self.__data_lists[col_type][col_index])
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
+ setattr(result, column_name, None)
- def __init__(self, addr=None, file_path=None, bin_path=None,
- unique_port=True):
+ self.__current_index += 1
+ return result
+
+ def __init__(self,
+ addr=None,
+ file_path=None,
+ bin_path=None,
+ unique_port=True,
+ verbose=False):
# 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)
+ bin_path=bin_path, unique_port=unique_port, verbose=verbose)
tp = TraceProcessorHttp(url)
self.http = tp
self.protos = ProtoFactory()
diff --git a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
index b5e2561..c909308 100644
--- a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
+++ b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
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
index 93de9e1..8f474c4 100644
--- a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
+++ b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
@@ -2,5 +2,5 @@
// SHA1(tools/gen_binary_descriptors)
// 9fc6d77de57ec76a80b76aa282f4c7cf5ce55eec
// SHA1(protos/perfetto/metrics/metrics.proto)
-// 64a90d4e7177aa7a8ba57919313037430848325c
+// d861d7b0dd079940872852cbb4a4dfc3d67ac672
\ No newline at end of file
diff --git a/src/trace_processor/python/perfetto/trace_processor/shell.py b/src/trace_processor/python/perfetto/trace_processor/shell.py
index 44da342..00749d1 100644
--- a/src/trace_processor/python/perfetto/trace_processor/shell.py
+++ b/src/trace_processor/python/perfetto/trace_processor/shell.py
@@ -21,11 +21,12 @@
from .loader import get_loader
-def load_shell(bin_path=None, unique_port=False):
+def load_shell(bin_path, unique_port, verbose):
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)
+ stdout=subprocess.DEVNULL,
+ stderr=None if verbose else subprocess.DEVNULL)
while True:
try:
diff --git a/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor b/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor
index e3e9b24..1212bcd 100644
--- a/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor
+++ b/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor
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
index 6e01bd0..ecdef65 100644
--- a/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor.sha1
+++ b/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor.sha1
@@ -2,5 +2,5 @@
// SHA1(tools/gen_binary_descriptors)
// 9fc6d77de57ec76a80b76aa282f4c7cf5ce55eec
// SHA1(protos/perfetto/trace_processor/trace_processor.proto)
-// b4135d9bc2551939bfdaa4d03423cf34a8fbcffb
+// 8ed3e45d389366979465140f6dcdbbb1356f323a
\ No newline at end of file
diff --git a/src/trace_processor/rpc/httpd.cc b/src/trace_processor/rpc/httpd.cc
index 2cdf80f..b46bd87 100644
--- a/src/trace_processor/rpc/httpd.cc
+++ b/src/trace_processor/rpc/httpd.cc
@@ -42,6 +42,15 @@
constexpr char kBindPort[] = "9001";
constexpr size_t kOmitContentLength = static_cast<size_t>(-1);
+// Sets the Access-Control-Allow-Origin: $origin on the following origins.
+// This affects only browser clients that use CORS. Other HTTP clients (e.g. the
+// python API) don't look at CORS headers.
+const char* kAllowedCORSOrigins[] = {
+ "https://ui.perfetto.dev",
+ "http://localhost:10000",
+ "http://127.0.0.1:10000",
+};
+
// 32 MiB payload + 128K for HTTP headers.
constexpr size_t kMaxRequestSize = (32 * 1024 + 128) * 1024;
@@ -77,6 +86,7 @@
private:
size_t ParseOneHttpRequest(Client* client);
void HandleRequest(Client*, const HttpRequest&);
+ void ServeHelpPage(Client*);
void OnNewIncomingConnection(base::UnixSocket*,
std::unique_ptr<base::UnixSocket>) override;
@@ -90,6 +100,7 @@
std::unique_ptr<base::UnixSocket> sock6_;
std::list<Client> clients_;
Client* active_client_ = nullptr;
+ bool origin_error_logged_ = false;
};
HttpServer* g_httpd_instance;
@@ -113,6 +124,8 @@
Append(response, http_code);
Append(response, "\r\n");
for (const char* hdr : headers) {
+ if (strlen(hdr) == 0)
+ continue;
Append(response, hdr);
Append(response, "\r\n");
}
@@ -140,6 +153,11 @@
void HttpServer::Run(const char* kBindAddr4, const char* kBindAddr6) {
PERFETTO_ILOG("[HTTP] Starting RPC server on %s and %s", kBindAddr4,
kBindAddr6);
+ PERFETTO_LOG(
+ "[HTTP] This server can be used by reloading https://ui.perfetto.dev and "
+ "clicking on YES on the \"Trace Processor native acceleration\" dialog "
+ "or through the Python API (see "
+ "https://perfetto.dev/docs/analysis/trace-processor#python-api).");
sock4_ = base::UnixSocket::Listen(kBindAddr4, this, &task_runner_,
base::SockFamily::kInet,
@@ -274,6 +292,11 @@
}
void HttpServer::HandleRequest(Client* client, const HttpRequest& req) {
+ if (req.uri == "/") {
+ // If a user tries to open http://127.0.0.1:9001/ show a minimal help page.
+ return ServeHelpPage(client);
+ }
+
static int last_req_id = 0;
if (req.id) {
if (last_req_id && req.id != last_req_id + 1 && req.id != 1)
@@ -281,20 +304,36 @@
last_req_id = req.id;
}
- PERFETTO_LOG("[HTTP] %04d %s %s (body: %zu bytes)", req.id,
+ PERFETTO_LOG("[HTTP] %04d %s %s (body: %zu bytes).", req.id,
req.method.ToStdString().c_str(), req.uri.ToStdString().c_str(),
req.body.size());
- std::string allow_origin_hdr =
- "Access-Control-Allow-Origin: " + req.origin.ToStdString();
+
+ std::string allow_origin_hdr;
+ for (const char* allowed_origin : kAllowedCORSOrigins) {
+ if (req.origin != base::StringView(allowed_origin))
+ continue;
+ allow_origin_hdr =
+ "Access-Control-Allow-Origin: " + req.origin.ToStdString();
+ break;
+ }
+ if (allow_origin_hdr.empty() && !origin_error_logged_) {
+ origin_error_logged_ = true;
+ PERFETTO_ELOG(
+ "The HTTP origin \"%s\" is not trusted, no Access-Control-Allow-Origin "
+ "will be emitted. If this request comes from a browser it will fail. "
+ "For the list of allowed origins see kAllowedCORSOrigins.",
+ req.origin.ToStdString().c_str());
+ }
// 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, //
+ "Connection: Keep-Alive", //
+ "Cache-Control: no-cache", //
+ "Keep-Alive: timeout=5, max=1000", //
+ "Content-Type: application/x-protobuf", //
+ "Vary: Origin", //
+ transfer_encoding_hdr, //
allow_origin_hdr.c_str(),
};
@@ -305,6 +344,7 @@
"Access-Control-Allow-Methods: POST, GET, OPTIONS",
"Access-Control-Allow-Headers: *",
"Access-Control-Max-Age: 86400",
+ "Vary: Origin",
allow_origin_hdr.c_str(),
});
}
@@ -439,6 +479,38 @@
srv.Run(ipv4_addr.c_str(), ipv6_addr.c_str());
}
+void HttpServer::ServeHelpPage(Client* client) {
+ static const char kPage[] = R"(Perfetto Trace Processor RPC Server
+
+
+This service can be used in two ways:
+
+1. Open or reload https://ui.perfetto.dev/
+
+It will automatically try to connect and use the server on localhost:9001 when
+available. Click YES when prompted to use Trace Processor Native Acceleration
+in the UI dialog.
+See https://perfetto.dev/docs/visualization/large-traces for more.
+
+
+2. Python API.
+
+Example: perfetto.TraceProcessor(addr='localhost:9001')
+See https://perfetto.dev/docs/analysis/trace-processor#python-api for more.
+
+
+For questions:
+https://perfetto.dev/docs/contributing/getting-started#community
+)";
+
+ char content_length[255];
+ sprintf(content_length, "Content-Length: %zu", sizeof(kPage) - 1);
+ std::initializer_list<const char*> headers{"Content-Type: text/plain",
+ content_length};
+ HttpReply(client->sock.get(), "200 OK", headers,
+ reinterpret_cast<const uint8_t*>(kPage), sizeof(kPage) - 1);
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/sqlite/sqlite_raw_table.cc b/src/trace_processor/sqlite/sqlite_raw_table.cc
index b02abf4..9594887 100644
--- a/src/trace_processor/sqlite/sqlite_raw_table.cc
+++ b/src/trace_processor/sqlite/sqlite_raw_table.cc
@@ -16,7 +16,7 @@
#include "src/trace_processor/sqlite/sqlite_raw_table.h"
-#include <inttypes.h>
+#include <cinttypes>
#include "perfetto/base/compiler.h"
#include "perfetto/ext/base/string_utils.h"
@@ -29,6 +29,7 @@
#include "src/trace_processor/types/variadic.h"
#include "protos/perfetto/trace/ftrace/binder.pbzero.h"
+#include "protos/perfetto/trace/ftrace/cgroup.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"
@@ -58,7 +59,7 @@
ArgsSerializer(TraceProcessorContext*,
ArgSetId arg_set_id,
NullTermStringView event_name,
- std::vector<uint32_t>* field_id_to_arg_index,
+ std::vector<base::Optional<uint32_t>>* field_id_to_arg_index,
base::StringWriter*);
void SerializeArgs();
@@ -67,43 +68,35 @@
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);
- });
- }
-
+ // Arg writing functions.
void WriteArgForField(uint32_t field_id, ValueWriter writer) {
- WriteArgAtRow(FieldIdToRow(field_id), writer);
+ base::Optional<uint32_t> row = FieldIdToRow(field_id);
+ if (!row)
+ return;
+ WriteArgAtRow(*row, writer);
}
-
- void WriteValueForField(uint32_t field_id) {
- WriteValueForField(field_id,
- [this](const Variadic& v) { return WriteValue(v); });
+ void WriteArgForField(uint32_t field_id,
+ base::StringView key,
+ ValueWriter writer) {
+ base::Optional<uint32_t> row = FieldIdToRow(field_id);
+ if (!row)
+ return;
+ WriteArg(key, storage_->GetArgValue(*row), writer);
}
-
- void WriteValueForField(uint32_t field_id, SerializerValueWriter writer) {
- WriteValueForField(field_id, [this, writer](const Variadic& variadic) {
- (this->*writer)(variadic);
- });
+ void WriteArgAtRow(uint32_t arg_row, ValueWriter writer) {
+ const auto& args = storage_->arg_table();
+ const auto& key = storage_->GetString(args.key()[arg_row]);
+ WriteArg(key, storage_->GetArgValue(arg_row), writer);
}
+ void WriteArg(base::StringView key, Variadic value, ValueWriter writer);
+ // Value writing functions.
void WriteValueForField(uint32_t field_id, ValueWriter writer) {
- writer(storage_->GetArgValue(FieldIdToRow(field_id)));
+ base::Optional<uint32_t> row = FieldIdToRow(field_id);
+ if (!row)
+ return;
+ writer(storage_->GetArgValue(*row));
}
-
- void WriteArgAtRow(uint32_t arg_index) {
- WriteArgAtRow(arg_index,
- [this](const Variadic& v) { return WriteValue(v); });
- }
-
- void WriteArgAtRow(uint32_t arg_index, ValueWriter writer);
-
void WriteKernelFnValue(const Variadic& value) {
if (value.type == Variadic::Type::kUint) {
writer_->AppendHexInt(value.uint_value);
@@ -113,21 +106,30 @@
PERFETTO_DFATAL("Invalid field type %d", static_cast<int>(value.type));
}
}
-
void WriteValue(const Variadic& variadic);
- uint32_t FieldIdToRow(uint32_t field_id) {
+ // The default value writer which uses the |WriteValue| function.
+ ValueWriter DVW() { return Wrap(&ArgsSerializer::WriteValue); }
+ ValueWriter Wrap(SerializerValueWriter writer) {
+ return [this, writer](const Variadic& v) { (this->*writer)(v); };
+ }
+
+ // Converts a field id to a row in the args table.
+ base::Optional<uint32_t> FieldIdToRow(uint32_t field_id) {
PERFETTO_DCHECK(field_id > 0);
PERFETTO_DCHECK(field_id < field_id_to_arg_index_->size());
- uint32_t index_in_arg_set = (*field_id_to_arg_index_)[field_id];
- return start_row_ + index_in_arg_set;
+ base::Optional<uint32_t> index_in_arg_set =
+ (*field_id_to_arg_index_)[field_id];
+ return index_in_arg_set.has_value()
+ ? base::make_optional(start_row_ + *index_in_arg_set)
+ : base::nullopt;
}
const TraceStorage* storage_ = nullptr;
TraceProcessorContext* context_ = nullptr;
ArgSetId arg_set_id_ = kInvalidArgSetId;
NullTermStringView event_name_;
- std::vector<uint32_t>* field_id_to_arg_index_;
+ std::vector<base::Optional<uint32_t>>* field_id_to_arg_index_;
RowMap row_map_;
uint32_t start_row_ = 0;
@@ -135,11 +137,12 @@
base::StringWriter* writer_ = nullptr;
};
-ArgsSerializer::ArgsSerializer(TraceProcessorContext* context,
- ArgSetId arg_set_id,
- NullTermStringView event_name,
- std::vector<uint32_t>* field_id_to_arg_index,
- base::StringWriter* writer)
+ArgsSerializer::ArgsSerializer(
+ TraceProcessorContext* context,
+ ArgSetId arg_set_id,
+ NullTermStringView event_name,
+ std::vector<base::Optional<uint32_t>>* field_id_to_arg_index,
+ base::StringWriter* writer)
: context_(context),
arg_set_id_(arg_set_id),
event_name_(event_name),
@@ -195,9 +198,9 @@
if (event_name_ == "sched_switch") {
using SS = protos::pbzero::SchedSwitchFtraceEvent;
- WriteArgForField(SS::kPrevCommFieldNumber);
- WriteArgForField(SS::kPrevPidFieldNumber);
- WriteArgForField(SS::kPrevPrioFieldNumber);
+ WriteArgForField(SS::kPrevCommFieldNumber, DVW());
+ WriteArgForField(SS::kPrevPidFieldNumber, DVW());
+ WriteArgForField(SS::kPrevPrioFieldNumber, DVW());
WriteArgForField(SS::kPrevStateFieldNumber, [this](const Variadic& value) {
PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
auto state = static_cast<uint16_t>(value.int_value);
@@ -207,15 +210,15 @@
ftrace_utils::TaskState(state, kernel_version).ToString('|').data());
});
writer_->AppendLiteral(" ==>");
- WriteArgForField(SS::kNextCommFieldNumber);
- WriteArgForField(SS::kNextPidFieldNumber);
- WriteArgForField(SS::kNextPrioFieldNumber);
+ WriteArgForField(SS::kNextCommFieldNumber, DVW());
+ WriteArgForField(SS::kNextPidFieldNumber, DVW());
+ WriteArgForField(SS::kNextPrioFieldNumber, DVW());
return;
} else if (event_name_ == "sched_wakeup") {
using SW = protos::pbzero::SchedWakeupFtraceEvent;
- WriteArgForField(SW::kCommFieldNumber);
- WriteArgForField(SW::kPidFieldNumber);
- WriteArgForField(SW::kPrioFieldNumber);
+ WriteArgForField(SW::kCommFieldNumber, DVW());
+ WriteArgForField(SW::kPidFieldNumber, DVW());
+ WriteArgForField(SW::kPrioFieldNumber, DVW());
WriteArgForField(SW::kTargetCpuFieldNumber, [this](const Variadic& value) {
PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
writer_->AppendPaddedInt<'0', 3>(value.int_value);
@@ -224,28 +227,28 @@
} else if (event_name_ == "clock_set_rate") {
using CSR = protos::pbzero::ClockSetRateFtraceEvent;
writer_->AppendLiteral(" ");
- WriteValueForField(CSR::kNameFieldNumber);
- WriteArgForField(CSR::kStateFieldNumber);
- WriteArgForField(CSR::kCpuIdFieldNumber);
+ WriteValueForField(CSR::kNameFieldNumber, DVW());
+ WriteArgForField(CSR::kStateFieldNumber, DVW());
+ WriteArgForField(CSR::kCpuIdFieldNumber, DVW());
return;
} else if (event_name_ == "clk_set_rate") {
using CSR = protos::pbzero::ClkSetRateFtraceEvent;
writer_->AppendLiteral(" ");
- WriteValueForField(CSR::kNameFieldNumber);
+ WriteValueForField(CSR::kNameFieldNumber, DVW());
writer_->AppendLiteral(" ");
- WriteValueForField(CSR::kRateFieldNumber);
+ WriteValueForField(CSR::kRateFieldNumber, DVW());
return;
} else if (event_name_ == "clock_enable") {
using CE = protos::pbzero::ClockEnableFtraceEvent;
- WriteValueForField(CE::kNameFieldNumber);
- WriteArgForField(CE::kStateFieldNumber);
- WriteArgForField(CE::kCpuIdFieldNumber);
+ WriteValueForField(CE::kNameFieldNumber, DVW());
+ WriteArgForField(CE::kStateFieldNumber, DVW());
+ WriteArgForField(CE::kCpuIdFieldNumber, DVW());
return;
} else if (event_name_ == "clock_disable") {
using CD = protos::pbzero::ClockDisableFtraceEvent;
- WriteValueForField(CD::kNameFieldNumber);
- WriteArgForField(CD::kStateFieldNumber);
- WriteArgForField(CD::kCpuIdFieldNumber);
+ WriteValueForField(CD::kNameFieldNumber, DVW());
+ WriteArgForField(CD::kStateFieldNumber, DVW());
+ WriteArgForField(CD::kCpuIdFieldNumber, DVW());
return;
} else if (event_name_ == "binder_transaction") {
using BT = protos::pbzero::BinderTransactionFtraceEvent;
@@ -263,13 +266,13 @@
});
writer_->AppendString(" dest_proc=");
- WriteValueForField(BT::kToProcFieldNumber);
+ WriteValueForField(BT::kToProcFieldNumber, DVW());
writer_->AppendString(" dest_thread=");
- WriteValueForField(BT::kToThreadFieldNumber);
+ WriteValueForField(BT::kToThreadFieldNumber, DVW());
writer_->AppendString(" reply=");
- WriteValueForField(BT::kReplyFieldNumber);
+ WriteValueForField(BT::kReplyFieldNumber, DVW());
writer_->AppendString(" flags=0x");
WriteValueForField(BT::kFlagsFieldNumber, [this](const Variadic& value) {
@@ -291,8 +294,8 @@
PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
writer_->AppendUnsignedInt(static_cast<uint32_t>(value.int_value));
});
- WriteArgForField(BTAB::kDataSizeFieldNumber);
- WriteArgForField(BTAB::kOffsetsSizeFieldNumber);
+ WriteArgForField(BTAB::kDataSizeFieldNumber, DVW());
+ WriteArgForField(BTAB::kOffsetsSizeFieldNumber, DVW());
return;
} else if (event_name_ == "binder_transaction_received") {
using BTR = protos::pbzero::BinderTransactionReceivedFtraceEvent;
@@ -321,7 +324,7 @@
});
writer_->AppendString(" page=0000000000000000");
writer_->AppendString(" pfn=");
- WriteValueForField(MFA::kPfnFieldNumber);
+ WriteValueForField(MFA::kPfnFieldNumber, DVW());
writer_->AppendString(" ofs=");
WriteValueForField(MFA::kIndexFieldNumber, [this](const Variadic& value) {
PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
@@ -345,10 +348,10 @@
return;
} else if (event_name_ == "sched_blocked_reason") {
using SBR = protos::pbzero::SchedBlockedReasonFtraceEvent;
- WriteArgForField(SBR::kPidFieldNumber);
- WriteArgForField(SBR::kIoWaitFieldNumber);
+ WriteArgForField(SBR::kPidFieldNumber, DVW());
+ WriteArgForField(SBR::kIoWaitFieldNumber, DVW());
WriteArgForField(SBR::kCallerFieldNumber,
- &ArgsSerializer::WriteKernelFnValue);
+ Wrap(&ArgsSerializer::WriteKernelFnValue));
return;
} else if (event_name_ == "workqueue_activate_work") {
using WAW = protos::pbzero::WorkqueueActivateWorkFtraceEvent;
@@ -367,7 +370,7 @@
});
writer_->AppendString(": function ");
WriteValueForField(WES::kFunctionFieldNumber,
- &ArgsSerializer::WriteKernelFnValue);
+ Wrap(&ArgsSerializer::WriteKernelFnValue));
return;
} else if (event_name_ == "workqueue_execute_end") {
using WE = protos::pbzero::WorkqueueExecuteEndFtraceEvent;
@@ -385,22 +388,22 @@
writer_->AppendHexInt(value.uint_value);
});
WriteArgForField(WQW::kFunctionFieldNumber,
- &ArgsSerializer::WriteKernelFnValue);
+ Wrap(&ArgsSerializer::WriteKernelFnValue));
WriteArgForField(WQW::kWorkqueueFieldNumber, [this](const Variadic& value) {
PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
writer_->AppendHexInt(value.uint_value);
});
- WriteValueForField(WQW::kReqCpuFieldNumber);
- WriteValueForField(WQW::kCpuFieldNumber);
+ WriteValueForField(WQW::kReqCpuFieldNumber, DVW());
+ WriteValueForField(WQW::kCpuFieldNumber, DVW());
return;
} else if (event_name_ == "irq_handler_entry") {
using IEN = protos::pbzero::IrqHandlerEntryFtraceEvent;
- WriteArgForField(IEN::kIrqFieldNumber);
- WriteArgForField(IEN::kNameFieldNumber);
+ WriteArgForField(IEN::kIrqFieldNumber, DVW());
+ WriteArgForField(IEN::kNameFieldNumber, DVW());
return;
} else if (event_name_ == "irq_handler_exit") {
using IEX = protos::pbzero::IrqHandlerExitFtraceEvent;
- WriteArgForField(IEX::kIrqFieldNumber);
+ WriteArgForField(IEX::kIrqFieldNumber, DVW());
writer_->AppendString(" ret=");
WriteValueForField(IEX::kRetFieldNumber, [this](const Variadic& value) {
PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
@@ -409,7 +412,7 @@
return;
} else if (event_name_ == "softirq_entry") {
using SIE = protos::pbzero::SoftirqEntryFtraceEvent;
- WriteArgForField(SIE::kVecFieldNumber);
+ WriteArgForField(SIE::kVecFieldNumber, DVW());
writer_->AppendString(" [action=");
WriteValueForField(SIE::kVecFieldNumber, [this](const Variadic& value) {
PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
@@ -419,7 +422,7 @@
return;
} else if (event_name_ == "softirq_exit") {
using SIX = protos::pbzero::SoftirqExitFtraceEvent;
- WriteArgForField(SIX::kVecFieldNumber);
+ WriteArgForField(SIX::kVecFieldNumber, DVW());
writer_->AppendString(" [action=");
WriteValueForField(SIX::kVecFieldNumber, [this](const Variadic& value) {
PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
@@ -434,11 +437,11 @@
writer_->AppendChar(static_cast<char>(value.uint_value));
});
writer_->AppendString("|");
- WriteValueForField(TMW::kPidFieldNumber);
+ WriteValueForField(TMW::kPidFieldNumber, DVW());
writer_->AppendString("|");
- WriteValueForField(TMW::kNameFieldNumber);
+ WriteValueForField(TMW::kNameFieldNumber, DVW());
writer_->AppendString("|");
- WriteValueForField(TMW::kValueFieldNumber);
+ WriteValueForField(TMW::kValueFieldNumber, DVW());
return;
} else if (event_name_ == "g2d_tracing_mark_write") {
using TMW = protos::pbzero::G2dTracingMarkWriteFtraceEvent;
@@ -447,25 +450,33 @@
writer_->AppendChar(static_cast<char>(value.uint_value));
});
writer_->AppendString("|");
- WriteValueForField(TMW::kPidFieldNumber);
+ WriteValueForField(TMW::kPidFieldNumber, DVW());
writer_->AppendString("|");
- WriteValueForField(TMW::kNameFieldNumber);
+ WriteValueForField(TMW::kNameFieldNumber, DVW());
writer_->AppendString("|");
- WriteValueForField(TMW::kValueFieldNumber);
+ WriteValueForField(TMW::kValueFieldNumber, DVW());
+ return;
+ } else if (event_name_ == "cgroup_attach_task") {
+ using CAT = protos::pbzero::CgroupAttachTaskFtraceEvent;
+ WriteArgForField(CAT::kDstRootFieldNumber, DVW());
+ WriteArgForField(CAT::kDstIdFieldNumber, DVW());
+ WriteArgForField(CAT::kCnameFieldNumber, "cgroup", DVW());
+ WriteArgForField(CAT::kDstLevelFieldNumber, DVW());
+ WriteArgForField(CAT::kDstPathFieldNumber, DVW());
+ WriteArgForField(CAT::kPidFieldNumber, DVW());
+ WriteArgForField(CAT::kCommFieldNumber, DVW());
return;
}
for (auto it = row_map_.IterateRows(); it; it.Next()) {
- WriteArgAtRow(it.row());
+ WriteArgAtRow(it.row(), DVW());
}
}
-void ArgsSerializer::WriteArgAtRow(uint32_t arg_row, ValueWriter writer) {
- const auto& args = storage_->arg_table();
- const auto& key = storage_->GetString(args.key()[arg_row]);
- auto value = storage_->GetArgValue(arg_row);
-
+void ArgsSerializer::WriteArg(base::StringView key,
+ Variadic value,
+ ValueWriter writer) {
writer_->AppendChar(' ');
- writer_->AppendString(key.c_str(), key.size());
+ writer_->AppendString(key.data(), key.size());
writer_->AppendChar('=');
if (key == "gfp_flags") {
@@ -543,7 +554,15 @@
uint32_t row = static_cast<uint32_t>(sqlite3_value_int64(argv[0]));
auto str = serializer_.SerializeToString(row);
- sqlite3_result_text(ctx, str.release(), -1, free);
+ if (str.get() == nullptr) {
+ char buffer[1024];
+ snprintf(buffer, base::ArraySize(buffer),
+ "to_ftrace: Cannot serialize row with id %u", row);
+ sqlite3_result_error(ctx, buffer, -1);
+ return;
+ }
+
+ sqlite3_result_text(ctx, str.release(), -1, str.get_deleter());
}
SystraceSerializer::SystraceSerializer(TraceProcessorContext* context)
@@ -558,10 +577,15 @@
char line[4096];
base::StringWriter writer(line, sizeof(line));
- SerializePrefix(raw_row, &writer);
-
StringId event_name_id = raw.name()[raw_row];
NullTermStringView event_name = storage_->GetString(event_name_id);
+ if (event_name.StartsWith("chrome_event.") ||
+ event_name.StartsWith("track_event.")) {
+ return ScopedCString(nullptr, nullptr);
+ }
+
+ SerializePrefix(raw_row, &writer);
+
writer.AppendChar(' ');
if (event_name == "print" || event_name == "g2d_tracing_mark_write" ||
event_name == "dpu_tracing_mark_write") {
diff --git a/src/trace_processor/sqlite/sqlite_raw_table.h b/src/trace_processor/sqlite/sqlite_raw_table.h
index 3722d9b..ce1b9ac 100644
--- a/src/trace_processor/sqlite/sqlite_raw_table.h
+++ b/src/trace_processor/sqlite/sqlite_raw_table.h
@@ -36,7 +36,8 @@
ScopedCString SerializeToString(uint32_t raw_row);
private:
- using StringIdMap = std::unordered_map<StringId, std::vector<uint32_t>>;
+ using StringIdMap =
+ std::unordered_map<StringId, std::vector<base::Optional<uint32_t>>>;
void SerializePrefix(uint32_t raw_row, base::StringWriter* writer);
diff --git a/src/trace_processor/sqlite/sqlite_table.cc b/src/trace_processor/sqlite/sqlite_table.cc
index 2540a75..d155c98 100644
--- a/src/trace_processor/sqlite/sqlite_table.cc
+++ b/src/trace_processor/sqlite/sqlite_table.cc
@@ -17,9 +17,10 @@
#include "src/trace_processor/sqlite/sqlite_table.h"
#include <ctype.h>
-#include <inttypes.h>
#include <string.h>
+
#include <algorithm>
+#include <cinttypes>
#include <map>
#include "perfetto/base/logging.h"
diff --git a/src/trace_processor/storage/stats.h b/src/trace_processor/storage/stats.h
index 4a05a74..ea71ef0 100644
--- a/src/trace_processor/storage/stats.h
+++ b/src/trace_processor/storage/stats.h
@@ -185,7 +185,11 @@
"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, "")
+ F(perf_guardrail_stop_ts, kIndexed, kDataLoss, kTrace, ""), \
+ F(sorter_push_event_out_of_order, kSingle, kError, kTrace, \
+ "Trace events are out of order event after sorting. This can happen " \
+ "due to many factors including clock sync drift, producers emitting " \
+ "events out of order or a bug in trace processor's logic of sorting.")
// clang-format on
enum Type {
diff --git a/src/trace_processor/tables/android_tables.h b/src/trace_processor/tables/android_tables.h
index 1686533..9aa2551 100644
--- a/src/trace_processor/tables/android_tables.h
+++ b/src/trace_processor/tables/android_tables.h
@@ -40,7 +40,7 @@
C(int64_t, ts) \
C(uint32_t, utid) \
C(uint32_t, prio) \
- C(StringPool::Id, tag) \
+ C(base::Optional<StringPool::Id>, tag) \
C(StringPool::Id, msg)
PERFETTO_TP_TABLE(PERFETTO_TP_ANDROID_LOG_TABLE_DEF);
diff --git a/src/trace_processor/tables/profiler_tables.h b/src/trace_processor/tables/profiler_tables.h
index c51ac91..a42a6d9 100644
--- a/src/trace_processor/tables/profiler_tables.h
+++ b/src/trace_processor/tables/profiler_tables.h
@@ -233,6 +233,12 @@
PERFETTO_TP_TABLE(PERFETTO_TP_SYMBOL_DEF);
// Allocations that happened at a callsite.
+//
+//
+// NOTE: this table is not sorted by timestamp intentionanlly - see b/193757386
+// for details.
+// TODO(b/193757386): readd the sorted flag once this bug is fixed.
+//
// This is generated by heapprofd.
// @param ts the timestamp the allocations happened at. heapprofd batches
// allocations and frees, and all data from a dump will have the same
@@ -250,7 +256,7 @@
#define PERFETTO_TP_HEAP_PROFILE_ALLOCATION_DEF(NAME, PARENT, C) \
NAME(HeapProfileAllocationTable, "heap_profile_allocation") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
- C(int64_t, ts, Column::Flag::kSorted) \
+ C(int64_t, ts) \
C(uint32_t, upid) \
C(StringPool::Id, heap_name) \
C(StackProfileCallsiteTable::Id, callsite_id) \
diff --git a/src/trace_processor/tables/slice_tables.h b/src/trace_processor/tables/slice_tables.h
index 54272d8..8605ea9 100644
--- a/src/trace_processor/tables/slice_tables.h
+++ b/src/trace_processor/tables/slice_tables.h
@@ -33,8 +33,8 @@
C(int64_t, ts, Column::Flag::kSorted) \
C(int64_t, dur) \
C(TrackTable::Id, track_id) \
- C(StringPool::Id, category) \
- C(StringPool::Id, name) \
+ C(base::Optional<StringPool::Id>, category) \
+ C(base::Optional<StringPool::Id>, name) \
C(uint32_t, depth) \
C(int64_t, stack_id) \
C(int64_t, parent_stack_id) \
@@ -164,6 +164,21 @@
PERFETTO_TP_TABLE(PERFETTO_TP_THREAD_SLICE_DEF);
+#define PERFETTO_TP_EXPERIMENTAL_FLAT_SLICE_TABLE_DEF(NAME, PARENT, C) \
+ NAME(ExperimentalFlatSliceTable, "experimental_flat_slice") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(int64_t, ts) \
+ C(int64_t, dur) \
+ C(TrackTable::Id, track_id) \
+ C(base::Optional<StringPool::Id>, category) \
+ C(base::Optional<StringPool::Id>, name) \
+ C(uint32_t, arg_set_id) \
+ C(base::Optional<SliceTable::Id>, source_id) \
+ C(int64_t, start_bound, Column::Flag::kHidden) \
+ C(int64_t, end_bound, Column::Flag::kHidden)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_EXPERIMENTAL_FLAT_SLICE_TABLE_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..eb9774e 100644
--- a/src/trace_processor/tables/table_destructors.cc
+++ b/src/trace_processor/tables/table_destructors.cc
@@ -77,6 +77,7 @@
ThreadStateTable::~ThreadStateTable() = default;
ExpectedFrameTimelineSliceTable::~ExpectedFrameTimelineSliceTable() = default;
ActualFrameTimelineSliceTable::~ActualFrameTimelineSliceTable() = default;
+ExperimentalFlatSliceTable::~ExperimentalFlatSliceTable() = default;
// track_tables.h
TrackTable::~TrackTable() = default;
diff --git a/src/trace_processor/trace_database_integrationtest.cc b/src/trace_processor/trace_database_integrationtest.cc
index e963b54..fa61596 100644
--- a/src/trace_processor/trace_database_integrationtest.cc
+++ b/src/trace_processor/trace_database_integrationtest.cc
@@ -35,18 +35,58 @@
constexpr size_t kMaxChunkSize = 4 * 1024 * 1024;
+TEST(TraceProcessorCustomConfigTest, SkipInternalMetricsMatchingMountPath) {
+ auto config = Config();
+ config.skip_builtin_metric_paths = {"android/"};
+ auto processor = TraceProcessor::CreateInstance(config);
+ processor->NotifyEndOfFile();
+
+ // Check that andorid metrics have not been loaded.
+ auto it = processor->ExecuteQuery(
+ "select count(*) from trace_metrics "
+ "where name = 'android_cpu';");
+ ASSERT_TRUE(it.Next());
+ ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
+ ASSERT_EQ(it.Get(0).long_value, 0);
+
+ // Check that other metrics have been loaded.
+ it = processor->ExecuteQuery(
+ "select count(*) from trace_metrics "
+ "where name = 'trace_metadata';");
+ ASSERT_TRUE(it.Next());
+ ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
+ ASSERT_EQ(it.Get(0).long_value, 1);
+}
+
+TEST(TraceProcessorCustomConfigTest, HandlesMalformedMountPath) {
+ auto config = Config();
+ config.skip_builtin_metric_paths = {"", "androi"};
+ auto processor = TraceProcessor::CreateInstance(config);
+ processor->NotifyEndOfFile();
+
+ // Check that andorid metrics have been loaded.
+ auto it = processor->ExecuteQuery(
+ "select count(*) from trace_metrics "
+ "where name = 'android_cpu';");
+ ASSERT_TRUE(it.Next());
+ ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
+ ASSERT_EQ(it.Get(0).long_value, 1);
+}
+
class TraceProcessorIntegrationTest : public ::testing::Test {
public:
TraceProcessorIntegrationTest()
: processor_(TraceProcessor::CreateInstance(Config())) {}
protected:
- util::Status LoadTrace(const char* name, size_t min_chunk_size = 512) {
- EXPECT_LE(min_chunk_size, kMaxChunkSize);
+ util::Status LoadTrace(const char* name,
+ size_t min_chunk_size = 512,
+ size_t max_chunk_size = kMaxChunkSize) {
+ EXPECT_LE(min_chunk_size, max_chunk_size);
base::ScopedFstream f(fopen(
base::GetTestDataPath(std::string("test/data/") + name).c_str(), "rb"));
std::minstd_rand0 rnd_engine(0);
- std::uniform_int_distribution<size_t> dist(min_chunk_size, kMaxChunkSize);
+ std::uniform_int_distribution<size_t> dist(min_chunk_size, max_chunk_size);
while (!feof(*f)) {
size_t chunk_size = dist(rnd_engine);
std::unique_ptr<uint8_t[]> buf(new uint8_t[chunk_size]);
@@ -196,18 +236,30 @@
ASSERT_EQ(trace_metrics_count, 1);
}
-TEST_F(TraceProcessorIntegrationTest, ComputeMetricsFormatted) {
+TEST_F(TraceProcessorIntegrationTest, ComputeMetricsFormattedExtension) {
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());
+ // Extension fields are output as [fully.qualified.name].
ASSERT_EQ(metric_output,
- "test_chrome_metric: {\n"
+ "[perfetto.protos.test_chrome_metric]: {\n"
" test_value: 1\n"
"}");
}
+TEST_F(TraceProcessorIntegrationTest, ComputeMetricsFormattedNoExtension) {
+ std::string metric_output;
+ util::Status status = Processor()->ComputeMetricText(
+ std::vector<std::string>{"trace_metadata"},
+ TraceProcessor::MetricResultFormat::kProtoText, &metric_output);
+ ASSERT_TRUE(status.ok());
+ // Check that metric result starts with trace_metadata field. Since this is
+ // not an extension field, the field name is not fully qualified.
+ ASSERT_TRUE(metric_output.rfind("trace_metadata: {") == 0);
+}
+
// TODO(hjd): Add trace to test_data.
TEST_F(TraceProcessorIntegrationTest, DISABLED_AndroidBuildTrace) {
ASSERT_TRUE(LoadTrace("android_build_trace.json", strlen("[\n{")).ok());
@@ -363,6 +415,39 @@
ASSERT_EQ(it.Get(0).long_value, 276174);
}
+/*
+ * This trace does not have a uuid. The uuid will be generated from the first
+ * 4096 bytes, which will be read in one chunk.
+ */
+TEST_F(TraceProcessorIntegrationTest, TraceWithoutUuidReadInOneChunk) {
+ ASSERT_TRUE(LoadTrace("example_android_trace_30s.pb", kMaxChunkSize).ok());
+ auto it = Query("select str_value from metadata where name = 'trace_uuid'");
+ ASSERT_TRUE(it.Next());
+ EXPECT_STREQ(it.Get(0).string_value, "00000000-0000-0000-8906-ebb53e1d0738");
+}
+
+/*
+ * This trace does not have a uuid. The uuid will be generated from the first
+ * 4096 bytes, which will be read in multiple chunks.
+ */
+TEST_F(TraceProcessorIntegrationTest, TraceWithoutUuidReadInMultipleChuncks) {
+ ASSERT_TRUE(LoadTrace("example_android_trace_30s.pb", 512, 2048).ok());
+ auto it = Query("select str_value from metadata where name = 'trace_uuid'");
+ ASSERT_TRUE(it.Next());
+ EXPECT_STREQ(it.Get(0).string_value, "00000000-0000-0000-8906-ebb53e1d0738");
+}
+
+/*
+ * This trace has a uuid. It will not be overriden by the hash of the first 4096
+ * bytes.
+ */
+TEST_F(TraceProcessorIntegrationTest, TraceWithUuidReadInParts) {
+ ASSERT_TRUE(LoadTrace("trace_with_uuid.pftrace", 512, 2048).ok());
+ auto it = Query("select str_value from metadata where name = 'trace_uuid'");
+ ASSERT_TRUE(it.Next());
+ EXPECT_STREQ(it.Get(0).string_value, "123e4567-e89b-12d3-a456-426655443322");
+}
+
} // namespace
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index d03072d..ef98469 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -16,8 +16,8 @@
#include "src/trace_processor/trace_processor_impl.h"
-#include <inttypes.h>
#include <algorithm>
+#include <cinttypes>
#include "perfetto/base/logging.h"
#include "perfetto/base/time.h"
@@ -25,11 +25,12 @@
#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/descendant_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_flat_slice_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"
@@ -623,14 +624,48 @@
}
}
+void CreateUnwrapMetricProtoFunction(sqlite3* db) {
+ auto ret = sqlite3_create_function_v2(
+ db, "UNWRAP_METRIC_PROTO", 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr,
+ &metrics::UnwrapMetricProto, nullptr, nullptr, nullptr);
+ if (ret != SQLITE_OK) {
+ PERFETTO_FATAL("Error initializing UNWRAP_METRIC_PROTO: %s",
+ sqlite3_errmsg(db));
+ }
+}
+
+std::vector<std::string> SanitizeMetricMountPaths(
+ const std::vector<std::string>& mount_paths) {
+ std::vector<std::string> sanitized;
+ for (const auto& path : mount_paths) {
+ if (path.length() == 0)
+ continue;
+ sanitized.push_back(path);
+ if (path.back() != '/')
+ sanitized.back().append("/");
+ }
+ return sanitized;
+}
+
void SetupMetrics(TraceProcessor* tp,
sqlite3* db,
- std::vector<metrics::SqlMetricFile>* sql_metrics) {
- tp->ExtendMetricsProto(kMetricsDescriptor.data(), kMetricsDescriptor.size());
+ std::vector<metrics::SqlMetricFile>* sql_metrics,
+ const std::vector<std::string>& extension_paths) {
+ const std::vector<std::string> sanitized_extension_paths =
+ SanitizeMetricMountPaths(extension_paths);
+ std::vector<std::string> skip_prefixes;
+ skip_prefixes.reserve(sanitized_extension_paths.size());
+ for (const auto& path : sanitized_extension_paths) {
+ skip_prefixes.push_back(kMetricProtoRoot + path);
+ }
+ tp->ExtendMetricsProto(kMetricsDescriptor.data(), kMetricsDescriptor.size(),
+ skip_prefixes);
tp->ExtendMetricsProto(kAllChromeMetricsDescriptor.data(),
- kAllChromeMetricsDescriptor.size());
+ kAllChromeMetricsDescriptor.size(), skip_prefixes);
for (const auto& file_to_sql : metrics::sql_metrics::kFileToSql) {
+ if (base::StartsWithAny(file_to_sql.path, sanitized_extension_paths))
+ continue;
tp->RegisterMetric(file_to_sql.path, file_to_sql.sql);
}
@@ -718,8 +753,9 @@
CreateExtractArgFunction(context_.storage.get(), db);
CreateSourceGeqFunction(db);
CreateValueAtMaxTsFunction(db);
+ CreateUnwrapMetricProtoFunction(db);
- SetupMetrics(this, *db_, &sql_metrics_);
+ SetupMetrics(this, *db_, &sql_metrics_, cfg.skip_builtin_metric_paths);
// Setup the query cache.
query_cache_.reset(new QueryCache());
@@ -751,8 +787,14 @@
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<AncestorGenerator>(new AncestorGenerator(
+ AncestorGenerator::Ancestor::kSliceByStack, &context_)));
+ RegisterDynamicTable(
+ std::unique_ptr<DescendantGenerator>(new DescendantGenerator(
+ DescendantGenerator::Descendant::kSlice, &context_)));
+ RegisterDynamicTable(
+ std::unique_ptr<DescendantGenerator>(new DescendantGenerator(
+ DescendantGenerator::Descendant::kSliceByStack, &context_)));
RegisterDynamicTable(
std::unique_ptr<ConnectedFlowGenerator>(new ConnectedFlowGenerator(
ConnectedFlowGenerator::Mode::kDirectlyConnectedFlow, &context_)));
@@ -769,6 +811,8 @@
new ThreadStateGenerator(&context_)));
RegisterDynamicTable(std::unique_ptr<ExperimentalAnnotatedStackGenerator>(
new ExperimentalAnnotatedStackGenerator(&context_)));
+ RegisterDynamicTable(std::unique_ptr<ExperimentalFlatSliceGenerator>(
+ new ExperimentalFlatSliceGenerator(&context_)));
// New style db-backed tables.
RegisterDbTable(storage->arg_table());
@@ -998,7 +1042,15 @@
util::Status TraceProcessorImpl::ExtendMetricsProto(const uint8_t* data,
size_t size) {
- util::Status status = pool_.AddFromFileDescriptorSet(data, size);
+ return ExtendMetricsProto(data, size, /*skip_prefixes*/ {});
+}
+
+util::Status TraceProcessorImpl::ExtendMetricsProto(
+ const uint8_t* data,
+ size_t size,
+ const std::vector<std::string>& skip_prefixes) {
+ util::Status status =
+ pool_.AddFromFileDescriptorSet(data, size, skip_prefixes);
if (!status.ok())
return status;
diff --git a/src/trace_processor/trace_processor_impl.h b/src/trace_processor/trace_processor_impl.h
index cb9ef9f..5db351c 100644
--- a/src/trace_processor/trace_processor_impl.h
+++ b/src/trace_processor/trace_processor_impl.h
@@ -61,6 +61,11 @@
util::Status ExtendMetricsProto(const uint8_t* data, size_t size) override;
+ util::Status ExtendMetricsProto(
+ const uint8_t* data,
+ size_t size,
+ const std::vector<std::string>& skip_prefixes) override;
+
util::Status ComputeMetric(const std::vector<std::string>& metric_names,
std::vector<uint8_t>* metrics) override;
@@ -118,7 +123,6 @@
uint64_t bytes_parsed_ = 0;
};
-
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index 6925948..8caa693 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -15,12 +15,13 @@
*/
#include <errno.h>
#include <fcntl.h>
-#include <inttypes.h>
#include <stdio.h>
#include <sys/stat.h>
+#include <cinttypes>
#include <functional>
#include <iostream>
+#include <unordered_set>
#include <vector>
#include <google/protobuf/compiler/parser.h>
@@ -30,6 +31,7 @@
#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
+#include "perfetto/base/status.h"
#include "perfetto/base/time.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/getopt.h"
@@ -42,6 +44,7 @@
#include "perfetto/trace_processor/trace_processor.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/util/proto_to_json.h"
#include "src/trace_processor/util/status_macros.h"
@@ -343,23 +346,28 @@
return g_tp->RegisterMetric(path, sql);
}
-util::Status ExtendMetricsProto(const std::string& extend_metrics_proto,
- google::protobuf::DescriptorPool* pool) {
- google::protobuf::FileDescriptorSet desc_set;
-
- base::ScopedFile file(base::OpenFile(extend_metrics_proto, O_RDONLY));
+base::Status ParseToFileDescriptorProto(
+ const std::string& filename,
+ google::protobuf::FileDescriptorProto* file_desc) {
+ base::ScopedFile file(base::OpenFile(filename, O_RDONLY));
if (file.get() == -1) {
- return util::ErrStatus("Failed to open proto file %s",
- extend_metrics_proto.c_str());
+ return base::ErrStatus("Failed to open proto file %s", filename.c_str());
}
google::protobuf::io::FileInputStream stream(file.get());
ErrorPrinter printer;
google::protobuf::io::Tokenizer tokenizer(&stream, &printer);
- auto* file_desc = desc_set.add_file();
google::protobuf::compiler::Parser parser;
parser.Parse(&tokenizer, file_desc);
+ return base::OkStatus();
+}
+
+util::Status ExtendMetricsProto(const std::string& extend_metrics_proto,
+ google::protobuf::DescriptorPool* pool) {
+ google::protobuf::FileDescriptorSet desc_set;
+ auto* file_desc = desc_set.add_file();
+ RETURN_IF_ERROR(ParseToFileDescriptorProto(extend_metrics_proto, file_desc));
file_desc->set_name(BaseName(extend_metrics_proto));
pool->BuildFile(*file_desc);
@@ -382,35 +390,37 @@
util::Status RunMetrics(const std::vector<std::string>& metric_names,
OutputFormat format,
const google::protobuf::DescriptorPool& pool) {
+ if (format == OutputFormat::kTextProto) {
+ std::string out;
+ util::Status status =
+ g_tp->ComputeMetricText(metric_names, TraceProcessor::kProtoText, &out);
+ if (!status.ok()) {
+ return util::ErrStatus("Error when computing metrics: %s",
+ status.c_message());
+ }
+ out += '\n';
+ fwrite(out.c_str(), sizeof(char), out.size(), stdout);
+ return util::OkStatus();
+ }
+
std::vector<uint8_t> metric_result;
util::Status status = g_tp->ComputeMetric(metric_names, &metric_result);
if (!status.ok()) {
return util::ErrStatus("Error when computing metrics: %s",
status.c_message());
}
- if (format == OutputFormat::kNone) {
- return util::OkStatus();
- }
- if (format == OutputFormat::kBinaryProto) {
- fwrite(metric_result.data(), sizeof(uint8_t), metric_result.size(), stdout);
- return util::OkStatus();
- }
-
- google::protobuf::DynamicMessageFactory factory(&pool);
- auto* descriptor = pool.FindMessageTypeByName("perfetto.protos.TraceMetrics");
- std::unique_ptr<google::protobuf::Message> metrics(
- factory.GetPrototype(descriptor)->New());
- metrics->ParseFromArray(metric_result.data(),
- static_cast<int>(metric_result.size()));
switch (format) {
- case OutputFormat::kTextProto: {
- std::string out;
- google::protobuf::TextFormat::PrintToString(*metrics, &out);
- fwrite(out.c_str(), sizeof(char), out.size(), stdout);
- break;
- }
case OutputFormat::kJson: {
+ // TODO(b/182165266): Handle this using ComputeMetricText.
+ google::protobuf::DynamicMessageFactory factory(&pool);
+ auto* descriptor =
+ pool.FindMessageTypeByName("perfetto.protos.TraceMetrics");
+ std::unique_ptr<google::protobuf::Message> metrics(
+ factory.GetPrototype(descriptor)->New());
+ metrics->ParseFromArray(metric_result.data(),
+ static_cast<int>(metric_result.size()));
+
// We need to instantiate field options from dynamic message factory
// because otherwise it cannot parse our custom extensions.
const google::protobuf::Message* field_options_prototype =
@@ -422,9 +432,15 @@
break;
}
case OutputFormat::kBinaryProto:
+ fwrite(metric_result.data(), sizeof(uint8_t), metric_result.size(),
+ stdout);
+ break;
case OutputFormat::kNone:
- PERFETTO_FATAL("Unsupported output format.");
+ break;
+ case OutputFormat::kTextProto:
+ PERFETTO_FATAL("This case was already handled.");
}
+
return util::OkStatus();
}
@@ -526,10 +542,6 @@
return it->Status();
}
-bool IsBlankLine(const std::string& buffer) {
- return buffer == "\n" || buffer == "\r\n";
-}
-
bool IsCommentLine(const std::string& buffer) {
return base::StartsWith(buffer, "--");
}
@@ -545,8 +557,6 @@
std::string sql_query;
while (fgets(buffer, sizeof(buffer), input)) {
std::string line = base::TrimLeading(buffer);
- if (IsBlankLine(line))
- break;
if (IsCommentLine(line))
continue;
@@ -656,6 +666,33 @@
return util::OkStatus();
}
+class MetricExtension {
+ public:
+ void SetDiskPath(std::string path) {
+ AddTrailingSlashIfNeeded(path);
+ disk_path_ = std::move(path);
+ }
+ void SetVirtualPath(std::string path) {
+ AddTrailingSlashIfNeeded(path);
+ virtual_path_ = std::move(path);
+ }
+
+ // Disk location. Ends with a trailing slash.
+ const std::string& disk_path() const { return disk_path_; }
+ // Virtual location. Ends with a trailing slash.
+ const std::string& virtual_path() const { return virtual_path_; }
+
+ private:
+ std::string disk_path_;
+ std::string virtual_path_;
+
+ static void AddTrailingSlashIfNeeded(std::string& path) {
+ if (path.length() > 0 && path[path.length() - 1] != '/') {
+ path.push_back('/');
+ }
+ }
+};
+
struct CommandLineOptions {
std::string perf_file_path;
std::string query_file_path;
@@ -665,6 +702,7 @@
std::string metric_output;
std::string trace_file_path;
std::string port_number;
+ std::vector<std::string> raw_metric_extensions;
bool launch_shell = false;
bool enable_httpd = false;
bool wide = false;
@@ -716,7 +754,12 @@
writing the resulting trace into FILE.
--full-sort Forces the trace processor into performing
a full sort ignoring any windowing
- logic.)",
+ logic.
+ --metric-extension DISK_PATH@VIRTUAL_PATH
+ Loads metric proto and sql files from
+ DISK_PATH/protos and DISK_PATH/sql
+ respectively, and mounts them onto
+ VIRTUAL_PATH.)",
argv[0]);
}
@@ -728,6 +771,7 @@
OPT_METRICS_OUTPUT,
OPT_FORCE_FULL_SORT,
OPT_HTTP_PORT,
+ OPT_METRIC_EXTENSION,
};
static const option long_options[] = {
@@ -746,6 +790,7 @@
{"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},
+ {"metric-extension", required_argument, nullptr, OPT_METRIC_EXTENSION},
{nullptr, 0, nullptr, 0}};
bool explicit_interactive = false;
@@ -832,6 +877,11 @@
continue;
}
+ if (option == OPT_METRIC_EXTENSION) {
+ command_line_options.raw_metric_extensions.push_back(optarg);
+ continue;
+ }
+
PrintUsage(argv);
exit(option == 'h' ? 0 : 1);
}
@@ -858,16 +908,20 @@
PrintUsage(argv);
exit(1);
}
+
return command_line_options;
}
void ExtendPoolWithBinaryDescriptor(google::protobuf::DescriptorPool& pool,
const void* data,
- int size) {
+ int size,
+ std::vector<std::string>& skip_prefixes) {
google::protobuf::FileDescriptorSet desc_set;
desc_set.ParseFromArray(data, size);
- for (const auto& desc : desc_set.file()) {
- pool.BuildFile(desc);
+ for (const auto& file_desc : desc_set.file()) {
+ if (base::StartsWithAny(file_desc.name(), skip_prefixes))
+ continue;
+ pool.BuildFile(file_desc);
}
}
@@ -941,16 +995,154 @@
return util::OkStatus();
}
-util::Status RunMetrics(const CommandLineOptions& options) {
- // Descriptor pool used for printing output as textproto.
- // Building on top of generated pool so default protos in
- // google.protobuf.descriptor.proto are available.
+base::Status ParseSingleMetricExtensionPath(const std::string& raw_extension,
+ MetricExtension& parsed_extension) {
+ // We cannot easily use ':' as a path separator because windows paths can have
+ // ':' in them (e.g. C:\foo\bar).
+ std::vector<std::string> parts = base::SplitString(raw_extension, "@");
+ if (parts.size() != 2 || parts[0].length() == 0 || parts[1].length() == 0) {
+ return base::ErrStatus(
+ "--metric-extension-dir must be of format disk_path@virtual_path");
+ }
+
+ parsed_extension.SetDiskPath(std::move(parts[0]));
+ parsed_extension.SetVirtualPath(std::move(parts[1]));
+
+ if (parsed_extension.virtual_path() == "shell/") {
+ return base::Status(
+ "Cannot have 'shell/' as metric extension virtual path.");
+ }
+ return util::OkStatus();
+}
+
+base::Status CheckForDuplicateMetricExtension(
+ const std::vector<MetricExtension>& metric_extensions) {
+ std::unordered_set<std::string> disk_paths;
+ std::unordered_set<std::string> virtual_paths;
+ for (const auto& extension : metric_extensions) {
+ auto ret = disk_paths.insert(extension.disk_path());
+ if (!ret.second) {
+ return base::ErrStatus(
+ "Another metric extension is already using disk path %s",
+ extension.disk_path().c_str());
+ }
+ ret = virtual_paths.insert(extension.virtual_path());
+ if (!ret.second) {
+ return base::ErrStatus(
+ "Another metric extension is already using virtual path %s",
+ extension.virtual_path().c_str());
+ }
+ }
+ return base::OkStatus();
+}
+
+base::Status ParseMetricExtensionPaths(
+ const std::vector<std::string>& raw_metric_extensions,
+ std::vector<MetricExtension>& metric_extensions) {
+ for (const auto& raw_extension : raw_metric_extensions) {
+ metric_extensions.push_back({});
+ RETURN_IF_ERROR(ParseSingleMetricExtensionPath(raw_extension,
+ metric_extensions.back()));
+ }
+ return CheckForDuplicateMetricExtension(metric_extensions);
+}
+
+base::Status LoadMetricExtensionProtos(const std::string& proto_root,
+ const std::string& mount_path) {
+ if (!base::FileExists(proto_root)) {
+ return base::ErrStatus(
+ "Directory %s does not exist. Metric extension directory must contain "
+ "a 'sql/' and 'protos/' subdirectory.",
+ proto_root.c_str());
+ }
+ std::vector<std::string> proto_files;
+ RETURN_IF_ERROR(base::ListFilesRecursive(proto_root, proto_files));
+
+ google::protobuf::FileDescriptorSet parsed_protos;
+ for (const auto& file_path : proto_files) {
+ if (base::GetFileExtension(file_path) != ".proto")
+ continue;
+ auto* file_desc = parsed_protos.add_file();
+ ParseToFileDescriptorProto(proto_root + file_path, file_desc);
+ file_desc->set_name(mount_path + file_path);
+ }
+
+ std::vector<uint8_t> serialized_filedescset;
+ serialized_filedescset.resize(parsed_protos.ByteSizeLong());
+ parsed_protos.SerializeToArray(
+ serialized_filedescset.data(),
+ static_cast<int>(serialized_filedescset.size()));
+
+ RETURN_IF_ERROR(g_tp->ExtendMetricsProto(serialized_filedescset.data(),
+ serialized_filedescset.size()));
+
+ return base::OkStatus();
+}
+
+base::Status LoadMetricExtensionSql(const std::string& sql_root,
+ const std::string& mount_path) {
+ if (!base::FileExists(sql_root)) {
+ return base::ErrStatus(
+ "Directory %s does not exist. Metric extension directory must contain "
+ "a 'sql/' and 'protos/' subdirectory.",
+ sql_root.c_str());
+ }
+
+ std::vector<std::string> sql_files;
+ RETURN_IF_ERROR(base::ListFilesRecursive(sql_root, sql_files));
+ for (const auto& file_path : sql_files) {
+ if (base::GetFileExtension(file_path) != ".sql")
+ continue;
+ std::string file_contents;
+ if (!base::ReadFile(sql_root + file_path, &file_contents)) {
+ return base::ErrStatus("Cannot read file %s", file_path.c_str());
+ }
+ RETURN_IF_ERROR(
+ g_tp->RegisterMetric(mount_path + file_path, file_contents));
+ }
+
+ return base::OkStatus();
+}
+
+base::Status LoadMetricExtension(const MetricExtension& extension) {
+ const std::string& disk_path = extension.disk_path();
+ const std::string& virtual_path = extension.virtual_path();
+
+ if (!base::FileExists(disk_path)) {
+ return base::ErrStatus("Metric extension directory %s does not exist",
+ disk_path.c_str());
+ }
+
+ // Note: Proto files must be loaded first, because we determine whether an SQL
+ // file is a metric or not by checking if the name matches a field of the root
+ // TraceMetrics proto.
+ RETURN_IF_ERROR(LoadMetricExtensionProtos(disk_path + "protos/",
+ kMetricProtoRoot + virtual_path));
+ RETURN_IF_ERROR(LoadMetricExtensionSql(disk_path + "sql/", virtual_path));
+
+ return base::OkStatus();
+}
+
+util::Status RunMetrics(const CommandLineOptions& options,
+ std::vector<MetricExtension>& metric_extensions) {
+ // Descriptor pool used for printing output as textproto. Building on top of
+ // generated pool so default protos in google.protobuf.descriptor.proto are
+ // available.
google::protobuf::DescriptorPool pool(
google::protobuf::DescriptorPool::generated_pool());
+ // TODO(b/182165266): There is code duplication here with trace_processor_impl
+ // SetupMetrics. This will be removed when we switch the output formatter to
+ // use internal DescriptorPool.
+ std::vector<std::string> skip_prefixes;
+ skip_prefixes.reserve(metric_extensions.size());
+ for (const auto& ext : metric_extensions) {
+ skip_prefixes.push_back(kMetricProtoRoot + ext.virtual_path());
+ }
ExtendPoolWithBinaryDescriptor(pool, kMetricsDescriptor.data(),
- kMetricsDescriptor.size());
+ kMetricsDescriptor.size(), skip_prefixes);
ExtendPoolWithBinaryDescriptor(pool, kAllChromeMetricsDescriptor.data(),
- kAllChromeMetricsDescriptor.size());
+ kAllChromeMetricsDescriptor.size(),
+ skip_prefixes);
std::vector<std::string> metrics;
for (base::StringSplitter ss(options.metric_names, ','); ss.Next();) {
@@ -995,6 +1187,7 @@
} else {
format = OutputFormat::kTextProto;
}
+
return RunMetrics(std::move(metrics), format, pool);
}
@@ -1058,6 +1251,14 @@
? SortingMode::kForceFullSort
: SortingMode::kDefaultHeuristics;
+ std::vector<MetricExtension> metric_extensions;
+ RETURN_IF_ERROR(ParseMetricExtensionPaths(options.raw_metric_extensions,
+ metric_extensions));
+
+ for (const auto& extension : metric_extensions) {
+ config.skip_builtin_metric_paths.push_back(extension.virtual_path());
+ }
+
std::unique_ptr<TraceProcessor> tp = TraceProcessor::CreateInstance(config);
g_tp = tp.get();
@@ -1066,6 +1267,13 @@
tp->EnableMetatrace();
}
+ // We load all the metric extensions even when --run-metrics arg is not there,
+ // because we want the metrics to be available in interactive mode or when
+ // used in UI using httpd.
+ for (const auto& extension : metric_extensions) {
+ RETURN_IF_ERROR(LoadMetricExtension(extension));
+ }
+
base::TimeNanos t_load{};
if (!options.trace_file_path.empty()) {
base::TimeNanos t_load_start = base::GetWallTimeNs();
@@ -1097,7 +1305,7 @@
}
if (!options.metric_names.empty()) {
- RETURN_IF_ERROR(RunMetrics(options));
+ RETURN_IF_ERROR(RunMetrics(options, metric_extensions));
}
if (!options.query_file_path.empty()) {
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index e9c0f37..b71eac7 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -17,6 +17,7 @@
#include "src/trace_processor/trace_processor_storage_impl.h"
#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/uuid.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"
@@ -37,7 +38,6 @@
#include "src/trace_processor/importers/track_event.descriptor.h"
#include "src/trace_processor/trace_sorter.h"
#include "src/trace_processor/util/descriptors.h"
-#include "src/trace_processor/util/trace_blob_view.h"
namespace perfetto {
namespace trace_processor {
@@ -94,6 +94,19 @@
auto scoped_trace = context_.storage->TraceExecutionTimeIntoStats(
stats::parse_trace_duration_ns);
+
+ if (hash_input_size_remaining_ > 0 && !context_.uuid_found_in_trace) {
+ const size_t hash_size = std::min(hash_input_size_remaining_, size);
+ hash_input_size_remaining_ -= hash_size;
+
+ trace_hash_.Update(reinterpret_cast<const char*>(data.get()), hash_size);
+ base::Uuid uuid(static_cast<int64_t>(trace_hash_.digest()), 0);
+ const StringId id_for_uuid =
+ context_.storage->InternString(base::StringView(uuid.ToPrettyString()));
+ context_.metadata_tracker->SetMetadata(metadata::trace_uuid,
+ Variadic::String(id_for_uuid));
+ }
+
util::Status status = context_.chunk_reader->Parse(std::move(data), size);
unrecoverable_parse_error_ |= !status.ok();
return status;
diff --git a/src/trace_processor/trace_processor_storage_impl.h b/src/trace_processor/trace_processor_storage_impl.h
index 1c029c6..4b225d0 100644
--- a/src/trace_processor/trace_processor_storage_impl.h
+++ b/src/trace_processor/trace_processor_storage_impl.h
@@ -19,6 +19,7 @@
#include <memory>
+#include "perfetto/ext/base/hash.h"
#include "perfetto/trace_processor/basic_types.h"
#include "perfetto/trace_processor/status.h"
#include "perfetto/trace_processor/trace_processor_storage.h"
@@ -38,8 +39,10 @@
TraceProcessorContext* context() { return &context_; }
protected:
+ base::Hash trace_hash_;
TraceProcessorContext context_;
bool unrecoverable_parse_error_ = false;
+ size_t hash_input_size_remaining_ = 4096;
};
} // namespace trace_processor
diff --git a/src/trace_processor/trace_sorter.cc b/src/trace_processor/trace_sorter.cc
index c1bc9e5..a3907dd 100644
--- a/src/trace_processor/trace_sorter.cc
+++ b/src/trace_processor/trace_sorter.cc
@@ -24,9 +24,12 @@
namespace perfetto {
namespace trace_processor {
-TraceSorter::TraceSorter(std::unique_ptr<TraceParser> parser,
- int64_t window_size_ns)
- : parser_(std::move(parser)), window_size_ns_(window_size_ns) {
+TraceSorter::TraceSorter(TraceProcessorContext* context,
+ std::unique_ptr<TraceParser> parser,
+ SortingMode sorting_mode)
+ : context_(context),
+ parser_(std::move(parser)),
+ sorting_mode_(sorting_mode) {
const char* env = getenv("TRACE_PROCESSOR_SORT_ONLY");
bypass_next_stage_for_testing_ = env && !strcmp(env, "1");
if (bypass_next_stage_for_testing_)
@@ -56,10 +59,10 @@
PERFETTO_DCHECK(std::is_sorted(events_.begin(), events_.end()));
}
-// Removes all the events in |queues_| that are earlier than the given window
-// size and moves them to the next parser stages, respecting global timestamp
-// order. This function is a "extract min from N sorted queues", with some
-// little cleverness: we know that events tend to be bursty, so events are
+// Removes all the events in |queues_| that are earlier than the given
+// packet index and moves them to the next parser stages, respecting global
+// timestamp order. This function is a "extract min from N sorted queues", with
+// some little cleverness: we know that events tend to be bursty, so events are
// not going to be randomly distributed on the N |queues_|.
// Upon each iteration this function finds the first two queues (if any) that
// have the oldest events, and extracts events from the 1st until hitting the
@@ -76,12 +79,8 @@
// to avoid re-scanning all the queues all the times) but doesn't seem worth it.
// With Android traces (that have 8 CPUs) this function accounts for ~1-3% cpu
// time in a profiler.
-void TraceSorter::SortAndExtractEventsBeyondWindow(int64_t window_size_ns) {
- DCHECK_ftrace_batch_cpu(kNoBatch);
-
+void TraceSorter::SortAndExtractEventsUntilPacket(uint64_t limit_packet_idx) {
constexpr int64_t kTsMax = std::numeric_limits<int64_t>::max();
- const bool was_empty = global_min_ts_ == kTsMax && global_max_ts_ == 0;
- int64_t extract_end_ts = global_max_ts_ - window_size_ns;
size_t iterations = 0;
for (;; iterations++) {
size_t min_queue_idx = 0; // The index of the queue with the min(ts).
@@ -122,13 +121,14 @@
PERFETTO_DCHECK(queue.min_ts_ == global_min_ts_);
// Now that we identified the min-queue, extract all events from it until
- // we hit either: (1) the min-ts of the 2nd queue or (2) the window limit,
- // whichever comes first.
- int64_t extract_until_ts = std::min(extract_end_ts, min_queue_ts[1]);
+ // we hit either: (1) the min-ts of the 2nd queue or (2) the packet index
+ // limit, whichever comes first.
size_t num_extracted = 0;
for (auto& event : events) {
- if (event.timestamp > extract_until_ts)
+ if (event.packet_idx >= limit_packet_idx ||
+ event.timestamp > min_queue_ts[1]) {
break;
+ }
++num_extracted;
MaybePushEvent(min_queue_idx, std::move(event));
@@ -162,12 +162,6 @@
}
} // for(;;)
- // We decide to extract events only when we know (using the global_{min,max}
- // bounds) that there are eligible events. We should never end up in a
- // situation where we call this function but then realize that there was
- // nothing to extract.
- PERFETTO_DCHECK(iterations > 0 || was_empty);
-
#if PERFETTO_DCHECK_IS_ON()
// Check that the global min/max are consistent.
int64_t dbg_min_ts = kTsMax;
@@ -182,10 +176,15 @@
}
void TraceSorter::MaybePushEvent(size_t queue_idx, TimestampedTracePiece ttp) {
+ int64_t timestamp = ttp.timestamp;
+ if (timestamp < latest_pushed_event_ts_)
+ context_->storage->IncrementStats(stats::sorter_push_event_out_of_order);
+
+ latest_pushed_event_ts_ = std::max(latest_pushed_event_ts_, timestamp);
+
if (PERFETTO_UNLIKELY(bypass_next_stage_for_testing_))
return;
- int64_t timestamp = ttp.timestamp;
if (queue_idx == 0) {
// queues_[0] is for non-ftrace packets.
parser_->ParseTracePacket(timestamp, std::move(ttp));
diff --git a/src/trace_processor/trace_sorter.h b/src/trace_processor/trace_sorter.h
index a93cd26..50bec23 100644
--- a/src/trace_processor/trace_sorter.h
+++ b/src/trace_processor/trace_sorter.h
@@ -39,21 +39,40 @@
// This class takes care of sorting events parsed from the trace stream in
// arbitrary order and pushing them to the next pipeline stages (parsing) in
// order. In order to support streaming use-cases, sorting happens within a
-// max window. Events are held in the TraceSorter staging area (events_) until
-// either (1) the (max - min) timestamp > window_size; (2) trace EOF.
+// window.
//
-// This class is designed around the assumption that:
+// Events are held in the TraceSorter staging area (events_) until either:
+// 1. We can determine that it's safe to extract events by observing
+// TracingServiceEvent Flush and ReadBuffer events
+// 2. The trace EOF is reached
+//
+// Incremental extraction
+//
+// Incremental extraction happens by using a combination of flush and read
+// buffer events from the tracing service. Note that incremental extraction
+// is only applicable for write_into_file traces; ring-buffer traces will
+// be sorted fully in-memory implicitly because there is only a single read
+// buffer call at the end.
+//
+// The algorithm for incremental extraction is explained in detail at
+// go/trace-sorting-is-complicated.
+//
+// Sorting algorithm
+//
+// The sorting algorithm is designed around the assumption that:
// - Most events come from ftrace.
// - Ftrace events are sorted within each cpu most of the times.
//
// Due to this, this class is oprerates as a streaming merge-sort of N+1 queues
// (N = num cpus + 1 for non-ftrace events). Each queue in turn gets sorted (if
// necessary) before proceeding with the global merge-sort-extract.
-// When an event is pushed through, it is just appeneded to the end of one of
+//
+// When an event is pushed through, it is just appended to the end of one of
// the N queues. While appending, we keep track of the fact that the queue
// is still ordered or just lost ordering. When an out-of-order event is
// detected on a queue we keep track of: (1) the offset within the queue where
// the chaos begun, (2) the timestamp that broke the ordering.
+//
// When we decide to extract events from the queues into the next stages of
// the trace processor, we re-sort the events in the queue. Rather than
// re-sorting everything all the times, we use the above knowledge to restrict
@@ -65,41 +84,43 @@
// from there to the end.
class TraceSorter {
public:
- TraceSorter(std::unique_ptr<TraceParser> parser, int64_t window_size_ns);
+ enum class SortingMode {
+ kDefault,
+ kFullSort,
+ };
+
+ TraceSorter(TraceProcessorContext* context,
+ std::unique_ptr<TraceParser> parser,
+ SortingMode);
inline void PushTracePacket(int64_t timestamp,
PacketSequenceState* state,
TraceBlobView packet) {
- DCHECK_ftrace_batch_cpu(kNoBatch);
- AppendNonFtraceAndMaybeExtractEvents(
- TimestampedTracePiece(timestamp, packet_idx_++, std::move(packet),
- state->current_generation()));
+ AppendNonFtraceEvent(TimestampedTracePiece(timestamp, packet_idx_++,
+ std::move(packet),
+ state->current_generation()));
}
inline void PushJsonValue(int64_t timestamp, std::string json_value) {
- DCHECK_ftrace_batch_cpu(kNoBatch);
- AppendNonFtraceAndMaybeExtractEvents(
+ AppendNonFtraceEvent(
TimestampedTracePiece(timestamp, packet_idx_++, std::move(json_value)));
}
inline void PushFuchsiaRecord(int64_t timestamp,
std::unique_ptr<FuchsiaRecord> record) {
- DCHECK_ftrace_batch_cpu(kNoBatch);
- AppendNonFtraceAndMaybeExtractEvents(
+ AppendNonFtraceEvent(
TimestampedTracePiece(timestamp, packet_idx_++, std::move(record)));
}
inline void PushSystraceLine(std::unique_ptr<SystraceLine> systrace_line) {
- DCHECK_ftrace_batch_cpu(kNoBatch);
-
int64_t timestamp = systrace_line->ts;
- AppendNonFtraceAndMaybeExtractEvents(TimestampedTracePiece(
- timestamp, packet_idx_++, std::move(systrace_line)));
+ AppendNonFtraceEvent(TimestampedTracePiece(timestamp, packet_idx_++,
+ std::move(systrace_line)));
}
inline void PushTrackEventPacket(int64_t timestamp,
std::unique_ptr<TrackEventData> data) {
- AppendNonFtraceAndMaybeExtractEvents(
+ AppendNonFtraceEvent(
TimestampedTracePiece(timestamp, packet_idx_++, std::move(data)));
}
@@ -107,65 +128,54 @@
int64_t timestamp,
TraceBlobView event,
PacketSequenceState* state) {
- set_ftrace_batch_cpu_for_DCHECK(cpu);
- GetQueue(cpu + 1)->Append(TimestampedTracePiece(
+ auto* queue = GetQueue(cpu + 1);
+ queue->Append(TimestampedTracePiece(
timestamp, packet_idx_++,
FtraceEventData{std::move(event), state->current_generation()}));
-
- // The caller must call FinalizeFtraceEventBatch() after having pushed a
- // batch of ftrace events. This is to amortize the overhead of handling
- // global ordering and doing that in batches only after all ftrace events
- // for a bundle are pushed.
+ UpdateGlobalTs(queue);
}
inline void PushInlineFtraceEvent(uint32_t cpu,
int64_t timestamp,
InlineSchedSwitch inline_sched_switch) {
- set_ftrace_batch_cpu_for_DCHECK(cpu);
- GetQueue(cpu + 1)->Append(
- TimestampedTracePiece(timestamp, packet_idx_++, inline_sched_switch));
-
- // As with |PushFtraceEvent|, doesn't immediately sort the affected queues.
// TODO(rsavitski): if a trace has a mix of normal & "compact" events (being
// pushed through this function), the ftrace batches will no longer be fully
// sorted by timestamp. In such situations, we will have to sort at the end
// of the batch. We can do better as both sub-sequences are sorted however.
// Consider adding extra queues, or pushing them in a merge-sort fashion
// instead.
+ auto* queue = GetQueue(cpu + 1);
+ queue->Append(
+ TimestampedTracePiece(timestamp, packet_idx_++, inline_sched_switch));
+ UpdateGlobalTs(queue);
}
inline void PushInlineFtraceEvent(uint32_t cpu,
int64_t timestamp,
InlineSchedWaking inline_sched_waking) {
- set_ftrace_batch_cpu_for_DCHECK(cpu);
- GetQueue(cpu + 1)->Append(
+ auto* queue = GetQueue(cpu + 1);
+ queue->Append(
TimestampedTracePiece(timestamp, packet_idx_++, inline_sched_waking));
- }
- inline void FinalizeFtraceEventBatch(uint32_t cpu) {
- DCHECK_ftrace_batch_cpu(cpu);
- set_ftrace_batch_cpu_for_DCHECK(kNoBatch);
- MaybeExtractEvents(GetQueue(cpu + 1));
+ UpdateGlobalTs(queue);
}
- // Extract all events ignoring the window.
void ExtractEventsForced() {
- SortAndExtractEventsBeyondWindow(/*window_size_ns=*/0);
+ SortAndExtractEventsUntilPacket(packet_idx_);
queues_.resize(0);
+
+ packet_idx_for_extraction_ = packet_idx_;
+ flushes_since_extraction_ = 0;
}
- // Sets the window size to be the size specified (which should be lower than
- // any previous window size specified) and flushes any data beyond
- // this window size.
- // It is undefined to call this function with a window size greater than than
- // the current size.
- void SetWindowSizeNs(int64_t window_size_ns) {
- PERFETTO_DCHECK(window_size_ns <= window_size_ns_);
+ void NotifyFlushEvent() { flushes_since_extraction_++; }
- PERFETTO_DLOG("Setting window size to be %" PRId64 " ns", window_size_ns);
- window_size_ns_ = window_size_ns;
-
- // Fast path: if, globally, we are within the window size, then just exit.
- if (global_max_ts_ - global_min_ts_ < window_size_ns)
+ void NotifyReadBufferEvent() {
+ if (sorting_mode_ == SortingMode::kFullSort ||
+ flushes_since_extraction_ < 2) {
return;
- SortAndExtractEventsBeyondWindow(window_size_ns_);
+ }
+
+ SortAndExtractEventsUntilPacket(packet_idx_for_extraction_);
+ packet_idx_for_extraction_ = packet_idx_;
+ flushes_since_extraction_ = 0;
}
int64_t max_timestamp() const { return global_max_ts_; }
@@ -210,9 +220,7 @@
int64_t sort_min_ts_ = std::numeric_limits<int64_t>::max();
};
- // This method passes any events older than window_size_ns to the
- // parser to be parsed and then stored.
- void SortAndExtractEventsBeyondWindow(int64_t windows_size_ns);
+ void SortAndExtractEventsUntilPacket(uint64_t limit_packet_idx);
inline Queue* GetQueue(size_t index) {
if (PERFETTO_UNLIKELY(index >= queues_.size()))
@@ -220,57 +228,40 @@
return &queues_[index];
}
- inline void AppendNonFtraceAndMaybeExtractEvents(TimestampedTracePiece ttp) {
- // Fast path: if this event is before all other events in the sorter and
- // happened more than the window size in the past, just push the event to
- // the next stage. This saves all the sorting logic which would simply move
- // this event to the head of the queue and then extract it out.
- //
- // In practice, these events will be rejected as being "out-of-order" later
- // on in trace processor (i.e. in EventTracker or SliceTracker); we don't
- // drop here to allow them to track packet drop stats.
- //
- // See b/188392852 for an example of where this condition would be hit in
- // practice.
- bool is_before_all_events = ttp.timestamp < global_max_ts_;
- bool is_before_window = global_max_ts_ - ttp.timestamp >= window_size_ns_;
- if (PERFETTO_UNLIKELY(is_before_all_events && is_before_window)) {
- MaybePushEvent(0, std::move(ttp));
- return;
- }
-
- // Slow path: append the event to the non-ftrace queue and extract any
- // events if available.
+ inline void AppendNonFtraceEvent(TimestampedTracePiece ttp) {
Queue* queue = GetQueue(0);
queue->Append(std::move(ttp));
- MaybeExtractEvents(queue);
+ UpdateGlobalTs(queue);
}
- inline void MaybeExtractEvents(Queue* queue) {
- DCHECK_ftrace_batch_cpu(kNoBatch);
- global_max_ts_ = std::max(global_max_ts_, queue->max_ts_);
+ inline void UpdateGlobalTs(Queue* queue) {
global_min_ts_ = std::min(global_min_ts_, queue->min_ts_);
-
- // Fast path: if, globally, we are within the window size, then just exit.
- if (global_max_ts_ - global_min_ts_ < window_size_ns_)
- return;
- SortAndExtractEventsBeyondWindow(window_size_ns_);
+ global_max_ts_ = std::max(global_max_ts_, queue->max_ts_);
}
void MaybePushEvent(size_t queue_idx,
TimestampedTracePiece ttp) PERFETTO_ALWAYS_INLINE;
+ TraceProcessorContext* context_;
std::unique_ptr<TraceParser> parser_;
+ // Whether we should ignore incremental extraction and just wait for
+ // forced extractionn at the end of the trace.
+ SortingMode sorting_mode_ = SortingMode::kDefault;
+
+ // The packet index until which events should be extracted. Set based
+ // on the packet index in |OnReadBuffer|.
+ uint64_t packet_idx_for_extraction_ = 0;
+
+ // The number of flushes which have happened since the last incremental
+ // extraction.
+ uint32_t flushes_since_extraction_ = 0;
+
// queues_[0] is the general (non-ftrace) queue.
// queues_[1] is the ftrace queue for CPU(0).
// queues_[x] is the ftrace queue for CPU(x - 1).
std::vector<Queue> queues_;
- // Events are propagated to the next stage only after (max - min) timestamp
- // is larger than this value.
- int64_t window_size_ns_;
-
// max(e.timestamp for e in queues_).
int64_t global_max_ts_ = 0;
@@ -283,23 +274,8 @@
// Used for performance tests. True when setting TRACE_PROCESSOR_SORT_ONLY=1.
bool bypass_next_stage_for_testing_ = false;
-#if PERFETTO_DCHECK_IS_ON()
- // Used only for DCHECK-ing that FinalizeFtraceEventBatch() is called.
- uint32_t ftrace_batch_cpu_ = kNoBatch;
-
- inline void DCHECK_ftrace_batch_cpu(uint32_t cpu) {
- PERFETTO_DCHECK(ftrace_batch_cpu_ == kNoBatch || ftrace_batch_cpu_ == cpu);
- }
-
- inline void set_ftrace_batch_cpu_for_DCHECK(uint32_t cpu) {
- PERFETTO_DCHECK(ftrace_batch_cpu_ == cpu || ftrace_batch_cpu_ == kNoBatch ||
- cpu == kNoBatch);
- ftrace_batch_cpu_ = cpu;
- }
-#else
- inline void DCHECK_ftrace_batch_cpu(uint32_t) {}
- inline void set_ftrace_batch_cpu_for_DCHECK(uint32_t) {}
-#endif
+ // max(e.ts for e pushed to next stage)
+ int64_t latest_pushed_event_ts_ = std::numeric_limits<int64_t>::min();
};
} // namespace trace_processor
diff --git a/src/trace_processor/trace_sorter_unittest.cc b/src/trace_processor/trace_sorter_unittest.cc
index b49f515..18c6d1e 100644
--- a/src/trace_processor/trace_sorter_unittest.cc
+++ b/src/trace_processor/trace_sorter_unittest.cc
@@ -76,13 +76,16 @@
: test_buffer_(std::unique_ptr<uint8_t[]>(new uint8_t[8]), 0, 8) {
storage_ = new NiceMock<MockTraceStorage>();
context_.storage.reset(storage_);
+ CreateSorter();
+ }
+ void CreateSorter(bool full_sort = true) {
std::unique_ptr<MockTraceParser> parser(new MockTraceParser(&context_));
parser_ = parser.get();
-
+ auto sorting_mode = full_sort ? TraceSorter::SortingMode::kFullSort
+ : TraceSorter::SortingMode::kDefault;
context_.sorter.reset(
- new TraceSorter(std::move(parser),
- std::numeric_limits<int64_t>::max() /*window_size*/));
+ new TraceSorter(&context_, std::move(parser), sorting_mode));
}
protected:
@@ -98,7 +101,6 @@
EXPECT_CALL(*parser_, MOCK_ParseFtracePacket(0, 1000, view.data(), 1));
context_.sorter->PushFtraceEvent(0 /*cpu*/, 1000 /*timestamp*/,
std::move(view), &state);
- context_.sorter->FinalizeFtraceEventBatch(0);
context_.sorter->ExtractEventsForced();
}
@@ -107,7 +109,6 @@
TraceBlobView view = test_buffer_.slice(0, 1);
EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1000, view.data(), 1));
context_.sorter->PushTracePacket(1000, &state, std::move(view));
- context_.sorter->FinalizeFtraceEventBatch(1000);
context_.sorter->ExtractEventsForced();
}
@@ -125,64 +126,134 @@
EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1100, view_3.data(), 3));
EXPECT_CALL(*parser_, MOCK_ParseFtracePacket(2, 1200, view_4.data(), 4));
- context_.sorter->SetWindowSizeNs(200);
context_.sorter->PushFtraceEvent(2 /*cpu*/, 1200 /*timestamp*/,
std::move(view_4), &state);
- 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);
-
- context_.sorter->FinalizeFtraceEventBatch(0);
context_.sorter->ExtractEventsForced();
}
-TEST_F(TraceSorterTest, SetWindowSize) {
+TEST_F(TraceSorterTest, IncrementalExtraction) {
+ CreateSorter(false);
+
PacketSequenceState state(&context_);
+
+ TraceBlobView view_1 = test_buffer_.slice(0, 1);
+ TraceBlobView view_2 = test_buffer_.slice(0, 2);
+ TraceBlobView view_3 = test_buffer_.slice(0, 3);
+ TraceBlobView view_4 = test_buffer_.slice(0, 4);
+ TraceBlobView view_5 = test_buffer_.slice(0, 5);
+
+ // Flush at the start of packet sequence to match behavior of the
+ // service.
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->PushTracePacket(1200, &state, std::move(view_2));
+ context_.sorter->PushTracePacket(1100, &state, std::move(view_1));
+
+ // No data should be exttracted at this point because we haven't
+ // seen two flushes yet.
+ context_.sorter->NotifyReadBufferEvent();
+
+ // Now that we've seen two flushes, we should be ready to start extracting
+ // data on the next OnReadBufer call (after two flushes as usual).
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->NotifyReadBufferEvent();
+
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->PushTracePacket(1400, &state, std::move(view_4));
+ context_.sorter->PushTracePacket(1300, &state, std::move(view_3));
+
+ // This ReadBuffer call should finally extract until the first OnReadBuffer
+ // call.
+ {
+ InSequence s;
+ EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1100, test_buffer_.data(), 1));
+ EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1200, test_buffer_.data(), 2));
+ }
+ context_.sorter->NotifyReadBufferEvent();
+
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->PushTracePacket(1500, &state, std::move(view_5));
+
+ // Nothing should be extracted as we haven't seen the second flush.
+ context_.sorter->NotifyReadBufferEvent();
+
+ // Now we've seen the second flush we should extract the next two packets.
+ context_.sorter->NotifyFlushEvent();
+ {
+ InSequence s;
+ EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1300, test_buffer_.data(), 3));
+ EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1400, test_buffer_.data(), 4));
+ }
+ context_.sorter->NotifyReadBufferEvent();
+
+ // The forced extraction should get the last packet.
+ EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1500, test_buffer_.data(), 5));
+ context_.sorter->ExtractEventsForced();
+}
+
+// Simulate a producer bug where the third packet is emitted
+// out of order. Verify that we track the stats correctly.
+TEST_F(TraceSorterTest, OutOfOrder) {
+ CreateSorter(false);
+
+ PacketSequenceState state(&context_);
+
TraceBlobView view_1 = test_buffer_.slice(0, 1);
TraceBlobView view_2 = test_buffer_.slice(0, 2);
TraceBlobView view_3 = test_buffer_.slice(0, 3);
TraceBlobView view_4 = test_buffer_.slice(0, 4);
- MockFunction<void(std::string check_point_name)> check;
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->PushTracePacket(1200, &state, std::move(view_2));
+ context_.sorter->PushTracePacket(1100, &state, std::move(view_1));
+ context_.sorter->NotifyReadBufferEvent();
+ // Both of the packets should have been pushed through.
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->NotifyFlushEvent();
{
InSequence s;
-
- EXPECT_CALL(*parser_, MOCK_ParseFtracePacket(0, 1000, view_1.data(), 1));
- EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1001, view_2.data(), 2));
- EXPECT_CALL(check, Call("1"));
- EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1100, view_3.data(), 3));
- EXPECT_CALL(check, Call("2"));
- EXPECT_CALL(*parser_, MOCK_ParseFtracePacket(2, 1200, view_4.data(), 4));
+ EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1100, test_buffer_.data(), 1));
+ EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1200, test_buffer_.data(), 2));
}
+ context_.sorter->NotifyReadBufferEvent();
- context_.sorter->SetWindowSizeNs(200);
- context_.sorter->PushFtraceEvent(2 /*cpu*/, 1200 /*timestamp*/,
- std::move(view_4), &state);
- context_.sorter->FinalizeFtraceEventBatch(2);
- context_.sorter->PushTracePacket(1001, &state, std::move(view_2));
- context_.sorter->PushTracePacket(1100, &state, std::move(view_3));
+ // Now, pass the third packet out of order.
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->PushTracePacket(1150, &state, std::move(view_3));
+ context_.sorter->NotifyReadBufferEvent();
- context_.sorter->PushFtraceEvent(0 /*cpu*/, 1000 /*timestamp*/,
- std::move(view_1), &state);
- context_.sorter->FinalizeFtraceEventBatch(0);
+ // The third packet should still be pushed through.
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->NotifyFlushEvent();
+ EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1150, test_buffer_.data(), 3));
+ context_.sorter->NotifyReadBufferEvent();
- // At this point, we should just flush the 1000 and 1001 packets.
- context_.sorter->SetWindowSizeNs(101);
+ // But we should also increment the stat that this was out of order.
+ ASSERT_EQ(
+ context_.storage->stats()[stats::sorter_push_event_out_of_order].value,
+ 1);
- // Inform the mock about where we are.
- check.Call("1");
+ // Push the fourth packet also out of order but after third.
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->NotifyFlushEvent();
+ context_.sorter->PushTracePacket(1170, &state, std::move(view_4));
+ context_.sorter->NotifyReadBufferEvent();
- // Now we should flush the 1100 packet.
- context_.sorter->SetWindowSizeNs(99);
-
- // Inform the mock about where we are.
- check.Call("2");
-
- // Now we should flush the 1200 packet.
+ // The fourt packet should still be pushed through.
+ EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1170, test_buffer_.data(), 4));
context_.sorter->ExtractEventsForced();
+
+ // But we should also increment the stat that this was out of order.
+ ASSERT_EQ(
+ context_.storage->stats()[stats::sorter_push_event_out_of_order].value,
+ 2);
}
// Simulates a random stream of ftrace events happening on random CPUs.
@@ -219,7 +290,6 @@
expectations[ts].push_back(cpu);
context_.sorter->PushFtraceEvent(cpu, ts, TraceBlobView(nullptr, 0, 0),
&state);
- context_.sorter->FinalizeFtraceEventBatch(cpu);
}
}
diff --git a/src/trace_processor/types/trace_processor_context.h b/src/trace_processor/types/trace_processor_context.h
index b2c63ba..1cf723c 100644
--- a/src/trace_processor/types/trace_processor_context.h
+++ b/src/trace_processor/types/trace_processor_context.h
@@ -118,6 +118,11 @@
std::vector<std::vector<ProtoImporterModule*>> modules_by_field;
std::vector<std::unique_ptr<ProtoImporterModule>> modules;
FtraceModule* ftrace_module = nullptr;
+
+ // Marks whether the uuid was read from the trace.
+ // If the uuid was NOT read, the uuid will be made from the hash of the first
+ // 4KB of the trace.
+ bool uuid_found_in_trace = false;
};
} // namespace trace_processor
diff --git a/src/trace_processor/util/descriptors.cc b/src/trace_processor/util/descriptors.cc
index 068da6f..0939d54 100644
--- a/src/trace_processor/util/descriptors.cc
+++ b/src/trace_processor/util/descriptors.cc
@@ -15,6 +15,8 @@
*/
#include "src/trace_processor/util/descriptors.h"
+
+#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/protozero/field.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
@@ -136,12 +138,13 @@
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()) {
+ if ((field.type() == FieldDescriptorProto::TYPE_MESSAGE ||
+ field.type() == FieldDescriptorProto::TYPE_ENUM) &&
+ field.raw_type_name() != existing_field->raw_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());
+ field.name().c_str(), field.raw_type_name().c_str(),
+ existing_field->raw_type_name().c_str());
}
}
}
@@ -208,15 +211,16 @@
util::Status DescriptorPool::AddFromFileDescriptorSet(
const uint8_t* file_descriptor_set_proto,
size_t size,
+ const std::vector<std::string>& skip_prefixes,
bool merge_existing_messages) {
- // 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();
+ const std::string file_name = file.name().ToStdString();
+ if (base::StartsWithAny(file_name, skip_prefixes))
+ continue;
if (processed_files_.find(file_name) != processed_files_.end()) {
// This file has been loaded once already. Skip.
continue;
diff --git a/src/trace_processor/util/descriptors.h b/src/trace_processor/util/descriptors.h
index a5c7cde..e4da7a0 100644
--- a/src/trace_processor/util/descriptors.h
+++ b/src/trace_processor/util/descriptors.h
@@ -158,9 +158,12 @@
class DescriptorPool {
public:
+ // Adds Descriptors from file_descriptor_set_proto. Ignores any FileDescriptor
+ // with name matching a prefix in |skip_prefixes|.
base::Status AddFromFileDescriptorSet(
const uint8_t* file_descriptor_set_proto,
size_t size,
+ const std::vector<std::string>& skip_prefixes = {},
bool merge_existing_messages = false);
base::Optional<uint32_t> FindDescriptorIdx(
diff --git a/src/trace_processor/util/gzip_utils.cc b/src/trace_processor/util/gzip_utils.cc
index 79cf1c0..b16e56b 100644
--- a/src/trace_processor/util/gzip_utils.cc
+++ b/src/trace_processor/util/gzip_utils.cc
@@ -40,9 +40,9 @@
#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
GzipDecompressor::GzipDecompressor() : z_stream_(new z_stream()) {
- z_stream_->zalloc = Z_NULL;
- z_stream_->zfree = Z_NULL;
- z_stream_->opaque = Z_NULL;
+ z_stream_->zalloc = nullptr;
+ z_stream_->zfree = nullptr;
+ z_stream_->opaque = nullptr;
inflateInit2(z_stream_.get(), 32 + 15);
}
#else
diff --git a/src/trace_processor/util/proto_to_json.cc b/src/trace_processor/util/proto_to_json.cc
index ff430c7..ea57dd6 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 QuoteAndEscapeJsonString(const std::string& raw) {
+ std::string ret;
+ for (auto it = raw.cbegin(); it != raw.cend(); it++) {
+ char c = *it;
+ switch (c) {
+ case '"':
+ // Double quote needs to be escaped.
+ ret += "\\\"";
+ break;
+ case '\n':
+ // Escape new line specially because it appears often and so is worth
+ // treating specially.
+ ret += "\\n";
+ break;
+ default:
+ if (c < 0x20) {
+ // All 32 ASCII control codes need to be escaped. Instead of using the
+ // short forms, we just always use \u escape sequences instead to make
+ // things simpler.
+ ret += "\\u00";
+
+ // Print |c| as a hex character. We reserve 3 bytes of space: 2 for
+ // the hex code and one for the null terminator.
+ char buf[3];
+ snprintf(buf, sizeof(buf), "%02X", c);
+ ret += buf;
+ } else {
+ // Everything else can be passed through directly.
+ ret += c;
+ }
+ 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 QuoteAndEscapeJsonString(
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 QuoteAndEscapeJsonString(
is_repeated ? ref->GetRepeatedString(message, field_desc, idx)
: ref->GetString(message, field_desc));
case FieldDescriptor::CppType::CPPTYPE_UINT32:
diff --git a/src/trace_processor/util/protozero_to_text.cc b/src/trace_processor/util/protozero_to_text.cc
index 43cf9b5..ce6b973 100644
--- a/src/trace_processor/util/protozero_to_text.cc
+++ b/src/trace_processor/util/protozero_to_text.cc
@@ -30,6 +30,63 @@
return value;
}
+// This function matches the implementation of TextFormatEscaper.escapeBytes
+// from the Java protobuf library.
+std::string QuoteAndEscapeTextProtoString(const std::string& raw) {
+ std::string ret;
+ for (auto it = raw.cbegin(); it != raw.cend(); it++) {
+ switch (*it) {
+ case '\a':
+ ret += "\\a";
+ 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;
+ case '\v':
+ ret += "\\v";
+ break;
+ case '\\':
+ ret += "\\\\";
+ break;
+ case '\'':
+ ret += "\\\'";
+ break;
+ case '"':
+ ret += "\\\"";
+ break;
+ default:
+ // Only ASCII characters between 0x20 (space) and 0x7e (tilde) are
+ // printable; other byte values are escaped with 3-character octal
+ // codes.
+ if (*it >= 0x20 && *it <= 0x7e) {
+ ret += *it;
+ } else {
+ ret += '\\';
+
+ // Cast to unsigned char to make the right shift unsigned as well.
+ unsigned char c = static_cast<unsigned char>(*it);
+ ret += ('0' + ((c >> 6) & 3));
+ ret += ('0' + ((c >> 3) & 7));
+ ret += ('0' + (c & 7));
+ }
+ break;
+ }
+ }
+ return '"' + ret + '"';
+}
+
// Recursively determine the size of all the string like things passed in the
// parameter pack |rest|.
size_t SizeOfStr() {
@@ -115,7 +172,7 @@
std::to_string(field.as_float()));
return;
case FieldDescriptorProto::TYPE_STRING: {
- auto s = base::QuoteAndEscapeControlCodes(field.as_std_string());
+ auto s = QuoteAndEscapeTextProtoString(field.as_std_string());
StrAppend(out, separator, indent, fd.name(), ": ", s);
return;
}
@@ -153,6 +210,20 @@
out->erase(out->size() - 2);
}
+std::string FormattedFieldDescriptorName(
+ const FieldDescriptor& field_descriptor) {
+ if (field_descriptor.is_extension()) {
+ // Libprotobuf formatter always formats extension field names as fully
+ // qualified names.
+ // TODO(b/197625974): Assuming for now all our extensions will belong to the
+ // perfetto.protos package. Update this if we ever want to support extendees
+ // in different package.
+ return "[perfetto.protos." + field_descriptor.name() + "]";
+ } else {
+ return field_descriptor.name();
+ }
+}
+
// Recursive case function, Will parse |protobytes| assuming it is a proto of
// |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
@@ -184,11 +255,11 @@
protos::pbzero::FieldDescriptorProto::TYPE_MESSAGE) {
if (include_new_lines) {
StrAppend(output, output->empty() ? "" : "\n", *indents,
- field_descriptor.name(), ": {");
+ FormattedFieldDescriptorName(field_descriptor), ": {");
IncreaseIndents(indents);
} else {
- StrAppend(output, output->empty() ? "" : " ", field_descriptor.name(),
- ": {");
+ StrAppend(output, output->empty() ? "" : " ",
+ FormattedFieldDescriptorName(field_descriptor), ": {");
}
ProtozeroToTextInternal(field_descriptor.resolved_type_name(),
field.as_bytes(), new_lines_mode, pool, indents,
diff --git a/src/tracebox/tracebox.cc b/src/tracebox/tracebox.cc
index ab2cae8..a79d4ee 100644
--- a/src/tracebox/tracebox.cc
+++ b/src/tracebox/tracebox.cc
@@ -113,7 +113,7 @@
if ((env = getenv("PERFETTO_CONSUMER_SOCK_NAME")))
consumer_socket = env;
if ((env = getenv("PERFETTO_PRODUCER_SOCK_NAME")))
- consumer_socket = env;
+ producer_socket = env;
base::SetEnv("PERFETTO_CONSUMER_SOCK_NAME", consumer_socket);
base::SetEnv("PERFETTO_PRODUCER_SOCK_NAME", producer_socket);
diff --git a/src/traced/probes/common/BUILD.gn b/src/traced/probes/common/BUILD.gn
index 4346c4e..94e9289 100644
--- a/src/traced/probes/common/BUILD.gn
+++ b/src/traced/probes/common/BUILD.gn
@@ -42,7 +42,7 @@
deps = [
":common",
"../../../../gn:default_deps",
- "../../../base",
+ "../../../base:test_support",
]
sources = [
"cpu_freq_info_for_testing.cc",
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..ddfa5d2 100644
--- a/src/traced/probes/common/cpu_freq_info_for_testing.cc
+++ b/src/traced/probes/common/cpu_freq_info_for_testing.cc
@@ -16,13 +16,8 @@
#include "src/traced/probes/common/cpu_freq_info_for_testing.h"
-#include <algorithm>
#include <memory>
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
-
namespace perfetto {
namespace {
@@ -40,53 +35,27 @@
} // namespace
-CpuFreqInfoForTesting::CpuFreqInfoForTesting()
- : fake_cpu_dir_(base::TempDir::Create()) {
+CpuFreqInfoForTesting::CpuFreqInfoForTesting() {
// Create a subset of /sys/devices/system/cpu.
- AddDir("cpuidle");
- AddDir("cpu0");
- AddDir("cpu0/cpufreq");
- AddFile("cpu0/cpufreq/scaling_available_frequencies",
+ tmpdir_.AddDir("cpuidle");
+ tmpdir_.AddDir("cpu0");
+ tmpdir_.AddDir("cpu0/cpufreq");
+ tmpdir_.AddFile("cpu0/cpufreq/scaling_available_frequencies",
kCpuFrequenciesAndroidLittleCore);
- AddFile("cpu0/cpufreq/scaling_boost_frequencies",
+ tmpdir_.AddFile("cpu0/cpufreq/scaling_boost_frequencies",
kCpuBoostFrequenciesAndroidLittleCore);
- AddDir("cpufreq");
- AddDir("cpu1");
- AddDir("cpu1/cpufreq");
- AddFile("cpu1/cpufreq/scaling_available_frequencies",
+ tmpdir_.AddDir("cpufreq");
+ tmpdir_.AddDir("cpu1");
+ tmpdir_.AddDir("cpu1/cpufreq");
+ tmpdir_.AddFile("cpu1/cpufreq/scaling_available_frequencies",
kCpuFrequenciesAndroidBigCore);
- AddFile("cpu1/cpufreq/scaling_boost_frequencies",
+ tmpdir_.AddFile("cpu1/cpufreq/scaling_boost_frequencies",
kCpuBoostFrequenciesAndroidBigCore);
- AddDir("power");
-}
-
-CpuFreqInfoForTesting::~CpuFreqInfoForTesting() {
- for (auto path : files_to_remove_)
- PERFETTO_CHECK(remove(AbsolutePath(path).c_str()) == 0);
- std::reverse(dirs_to_remove_.begin(), dirs_to_remove_.end());
- for (auto path : dirs_to_remove_)
- base::Rmdir(AbsolutePath(path));
+ tmpdir_.AddDir("power");
}
std::unique_ptr<CpuFreqInfo> CpuFreqInfoForTesting::GetInstance() {
- return std::unique_ptr<CpuFreqInfo>(new CpuFreqInfo(fake_cpu_dir_.path()));
-}
-
-void CpuFreqInfoForTesting::AddDir(std::string path) {
- dirs_to_remove_.push_back(path);
- base::Mkdir(AbsolutePath(path).c_str());
-}
-
-void CpuFreqInfoForTesting::AddFile(std::string path, std::string content) {
- files_to_remove_.push_back(path);
- base::ScopedFile fd(
- base::OpenFile(AbsolutePath(path), O_WRONLY | O_CREAT | O_TRUNC, 0600));
- PERFETTO_CHECK(base::WriteAll(fd.get(), content.c_str(), content.size()) ==
- static_cast<ssize_t>(content.size()));
-}
-
-std::string CpuFreqInfoForTesting::AbsolutePath(std::string path) {
- return fake_cpu_dir_.path() + "/" + path;
+ return std::unique_ptr<CpuFreqInfo>(new CpuFreqInfo(tmpdir_.path()));
}
} // namespace perfetto
diff --git a/src/traced/probes/common/cpu_freq_info_for_testing.h b/src/traced/probes/common/cpu_freq_info_for_testing.h
index e0e57c2..3ba3aa5 100644
--- a/src/traced/probes/common/cpu_freq_info_for_testing.h
+++ b/src/traced/probes/common/cpu_freq_info_for_testing.h
@@ -20,31 +20,19 @@
#include "src/traced/probes/common/cpu_freq_info.h"
#include <memory>
-#include <string>
-#include <vector>
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
+#include "src/base/test/tmp_dir_tree.h"
namespace perfetto {
class CpuFreqInfoForTesting {
public:
CpuFreqInfoForTesting();
- ~CpuFreqInfoForTesting();
std::unique_ptr<CpuFreqInfo> GetInstance();
private:
- base::TempDir fake_cpu_dir_;
- std::vector<std::string> dirs_to_remove_;
- std::vector<std::string> files_to_remove_;
-
- void AddDir(std::string path);
- void AddFile(std::string path, std::string content);
- void RmDir(std::string path);
- void RmFile(std::string path);
- std::string AbsolutePath(std::string path);
+ base::TmpDirTree tmpdir_;
};
} // namespace perfetto
diff --git a/src/traced/probes/ftrace/cpu_reader.cc b/src/traced/probes/ftrace/cpu_reader.cc
index facd4ce..c5f9168 100644
--- a/src/traced/probes/ftrace/cpu_reader.cc
+++ b/src/traced/probes/ftrace/cpu_reader.cc
@@ -66,11 +66,6 @@
uint32_t time_delta : 27;
};
-struct TimeStamp {
- uint64_t tv_nsec;
- uint64_t tv_sec;
-};
-
bool ReadIntoString(const uint8_t* start,
const uint8_t* end,
uint32_t field_id,
@@ -273,11 +268,15 @@
return pages_read;
for (FtraceDataSource* data_source : started_data_sources) {
- bool success = ProcessPagesForDataSource(
+ bool pages_parsed_ok = ProcessPagesForDataSource(
data_source->trace_writer(), data_source->mutable_metadata(), cpu_,
data_source->parsing_config(), parsing_buf, pages_read, table_,
- symbolizer_);
- PERFETTO_CHECK(success);
+ symbolizer_, ftrace_clock_);
+ // If this CHECK fires, it means that we did not know how to parse the
+ // kernel binary format. This is a bug in either perfetto or the kernel, and
+ // must be investigated. Hence we CHECK instead of recording a bit
+ // in the ftrace stats proto, which is easier to overlook.
+ PERFETTO_CHECK(pages_parsed_ok);
}
return pages_read;
@@ -292,7 +291,8 @@
const uint8_t* parsing_buf,
const size_t pages_read,
const ProtoTranslationTable* table,
- LazyKernelSymbolizer* symbolizer) {
+ LazyKernelSymbolizer* symbolizer,
+ protos::pbzero::FtraceClock ftrace_clock) {
// Allocate the buffer for compact scheduler events (which will be unused if
// the compact option isn't enabled).
CompactSchedBuffer compact_sched;
@@ -313,7 +313,6 @@
// 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
@@ -323,6 +322,7 @@
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;
@@ -351,9 +351,18 @@
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());
- metadata->last_kernel_addr_index_written = max_it_at_end;
+
+ // 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();
@@ -364,6 +373,8 @@
finalize_cur_packet();
packet = trace_writer->NewTracePacket();
bundle = packet->set_ftrace_events();
+ if (ftrace_clock)
+ bundle->set_ftrace_clock(ftrace_clock);
// 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.
@@ -372,6 +383,7 @@
bundle->set_lost_events(true);
};
+ bool pages_parsed_ok = 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);
@@ -406,13 +418,14 @@
ParsePagePayload(parse_pos, &page_header.value(), table, ds_config,
&compact_sched, bundle, metadata);
- // TODO(rsavitski): propagate error to trace processor in release builds.
- // (FtraceMetadata -> FtraceStats in trace).
- PERFETTO_DCHECK(evt_size == page_header->size);
+ if (evt_size != page_header->size) {
+ pages_parsed_ok = false;
+ PERFETTO_DFATAL("could not parse ftrace page");
+ }
}
finalize_cur_packet();
- return true;
+ return pages_parsed_ok;
}
// A page header consists of:
@@ -499,7 +512,7 @@
PERFETTO_DFATAL("Empty padding event.");
return 0;
}
- uint32_t length;
+ uint32_t length = 0;
if (!ReadAndAdvance<uint32_t>(&ptr, end, &length))
return 0;
// length includes itself (4 bytes)
@@ -510,20 +523,23 @@
}
case kTypeTimeExtend: {
// Extend the time delta.
- uint32_t time_delta_ext;
+ uint32_t time_delta_ext = 0;
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: {
- // Sync time stamp with external clock.
- TimeStamp time_stamp;
- if (!ReadAndAdvance<TimeStamp>(&ptr, end, &time_stamp))
+ // 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.
+ uint32_t time_delta_ext = 0;
+ if (!ReadAndAdvance<uint32_t>(&ptr, end, &time_delta_ext))
return 0;
- // Not implemented in the kernel, nothing should generate this.
- PERFETTO_DFATAL("Unimplemented in kernel. Should be unreachable.");
+ timestamp = event_header.time_delta +
+ (static_cast<uint64_t>(time_delta_ext) << 27);
break;
}
// Data record:
@@ -533,7 +549,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;
+ uint32_t event_size = 0;
if (event_header.type_or_length == 0) {
if (!ReadAndAdvance<uint32_t>(&ptr, end, &event_size))
return 0;
diff --git a/src/traced/probes/ftrace/cpu_reader.h b/src/traced/probes/ftrace/cpu_reader.h
index ba0f9fd..f0b4d09 100644
--- a/src/traced/probes/ftrace/cpu_reader.h
+++ b/src/traced/probes/ftrace/cpu_reader.h
@@ -49,6 +49,7 @@
namespace protos {
namespace pbzero {
class FtraceEventBundle;
+enum FtraceClock : int32_t;
} // namespace pbzero
} // namespace protos
@@ -239,7 +240,12 @@
const uint8_t* parsing_buf,
const size_t pages_read,
const ProtoTranslationTable* table,
- LazyKernelSymbolizer* symbolizer);
+ LazyKernelSymbolizer* symbolizer,
+ protos::pbzero::FtraceClock);
+
+ void set_ftrace_clock(protos::pbzero::FtraceClock clock) {
+ ftrace_clock_ = clock;
+ }
private:
CpuReader(const CpuReader&) = delete;
@@ -259,6 +265,7 @@
const ProtoTranslationTable* const table_;
LazyKernelSymbolizer* const symbolizer_;
base::ScopedFile trace_fd_;
+ protos::pbzero::FtraceClock ftrace_clock_{};
};
} // namespace perfetto
diff --git a/src/traced/probes/ftrace/cpu_reader_fuzzer.cc b/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
index db943a6..9119abd 100644
--- a/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
+++ b/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
@@ -23,12 +23,13 @@
#include "perfetto/ext/base/utils.h"
#include "perfetto/protozero/scattered_stream_null_delegate.h"
#include "perfetto/protozero/scattered_stream_writer.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
#include "src/traced/probes/ftrace/cpu_reader.h"
#include "src/traced/probes/ftrace/ftrace_config_muxer.h"
#include "src/traced/probes/ftrace/test/cpu_reader_support.h"
#include "src/tracing/core/null_trace_writer.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+
namespace perfetto {
namespace {
@@ -64,9 +65,9 @@
table->EventToFtraceId(GroupAndName("ftrace", "print")));
NullTraceWriter null_writer;
- CpuReader::ProcessPagesForDataSource(&null_writer, &metadata, /*cpu=*/0,
- &ds_config, g_page, /*pages_read=*/1,
- table, /*symbolizer*/ nullptr);
+ CpuReader::ProcessPagesForDataSource(
+ &null_writer, &metadata, /*cpu=*/0, &ds_config, g_page, /*pages_read=*/1,
+ table, /*symbolizer*/ nullptr, protos::pbzero::FTRACE_CLOCK_UNSPECIFIED);
}
} // namespace perfetto
diff --git a/src/traced/probes/ftrace/cpu_reader_unittest.cc b/src/traced/probes/ftrace/cpu_reader_unittest.cc
index 688dd7c..2669d4e 100644
--- a/src/traced/probes/ftrace/cpu_reader_unittest.cc
+++ b/src/traced/probes/ftrace/cpu_reader_unittest.cc
@@ -1069,7 +1069,7 @@
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<uint8_t>(0); // Deliberately mis-aligning.
writer.Write<uint32_t>(40 | 6 << 16);
writer.WriteFixedString(300, "Goodbye");
@@ -1181,9 +1181,9 @@
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
TraceWriterForTesting trace_writer;
- CpuReader::ProcessPagesForDataSource(&trace_writer, &metadata, /*cpu=*/1,
- &ds_config, buf, kTestPages, table,
- /*symbolizer=*/nullptr);
+ CpuReader::ProcessPagesForDataSource(
+ &trace_writer, &metadata, /*cpu=*/1, &ds_config, buf, kTestPages, table,
+ /*symbolizer=*/nullptr, protos::pbzero::FTRACE_CLOCK_UNSPECIFIED);
// Each packet should contain the parsed contents of a contiguous run of pages
// without data loss.
@@ -1202,6 +1202,251 @@
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;
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index b8c23e2..9422d52 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -569,6 +569,12 @@
{kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
"cname", 5, ProtoSchemaType::kString,
TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "dst_level", 6, ProtoSchemaType::kInt32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "dst_path", 7, ProtoSchemaType::kString,
+ TranslationStrategy::kInvalidTranslationStrategy},
},
kUnsetFtraceId,
67,
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.cc b/src/traced/probes/ftrace/ftrace_config_muxer.cc
index 0af1f2c..75c4466 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.cc
@@ -36,6 +36,8 @@
constexpr int kMaxPerCpuBufferSizeKb = 64 * 1024; // 64mb
// trace_clocks in preference order.
+// If this list is changed, the FtraceClocks enum in ftrace_event_bundle.proto
+// and FtraceConfigMuxer::SetupClock() should be also changed accordingly.
constexpr const char* kClocks[] = {"boot", "global", "local"};
void AddEventGroup(const ProtoTranslationTable* table,
@@ -654,8 +656,23 @@
if (current_clock == clock)
break;
ftrace_->SetClock(clock);
+ current_clock = clock;
break;
}
+
+ namespace pb0 = protos::pbzero;
+ if (current_clock == "boot") {
+ // "boot" is the default expectation on modern kernels, which is why we
+ // don't have an explicit FTRACE_CLOCK_BOOT enum and leave it unset.
+ // See comments in ftrace_event_bundle.proto.
+ current_state_.ftrace_clock = pb0::FTRACE_CLOCK_UNSPECIFIED;
+ } else if (current_clock == "global") {
+ current_state_.ftrace_clock = pb0::FTRACE_CLOCK_GLOBAL;
+ } else if (current_clock == "local") {
+ current_state_.ftrace_clock = pb0::FTRACE_CLOCK_LOCAL;
+ } else {
+ current_state_.ftrace_clock = pb0::FTRACE_CLOCK_UNKNOWN;
+ }
}
void FtraceConfigMuxer::SetupBufferSize(const FtraceConfig& request) {
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.h b/src/traced/probes/ftrace/ftrace_config_muxer.h
index 5aee63a..bcaf1e5 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.h
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.h
@@ -28,6 +28,12 @@
namespace perfetto {
+namespace protos {
+namespace pbzero {
+enum FtraceClock : int32_t;
+} // namespace pbzero
+} // namespace protos
+
// State held by the muxer per data source, used to parse ftrace according to
// that data source's config.
struct FtraceDataSourceConfig {
@@ -109,6 +115,10 @@
SetupClock(request);
}
+ protos::pbzero::FtraceClock ftrace_clock() const {
+ return current_state_.ftrace_clock;
+ }
+
std::set<GroupAndName> GetFtraceEventsForTesting(
const FtraceConfig& request,
const ProtoTranslationTable* table) {
@@ -130,6 +140,7 @@
std::vector<std::string> atrace_categories;
size_t cpu_buffer_size_pages = 0;
bool atrace_on = false;
+ protos::pbzero::FtraceClock ftrace_clock{};
};
FtraceConfigMuxer(const FtraceConfigMuxer&) = delete;
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
index 312f849..006ee59 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
@@ -745,6 +745,7 @@
FtraceConfig config;
FtraceConfigMuxer model(&ftrace, table_.get(), {});
+ namespace pb0 = protos::pbzero;
EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
.Times(AnyNumber());
@@ -753,19 +754,25 @@
.WillByDefault(Return("[local] global boot"));
EXPECT_CALL(ftrace, WriteToFile("/root/trace_clock", "boot"));
model.SetupClockForTesting(config);
+ // unspecified = boot.
+ EXPECT_EQ(model.ftrace_clock(),
+ static_cast<int>(pb0::FTRACE_CLOCK_UNSPECIFIED));
ON_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
.WillByDefault(Return("[local] global"));
EXPECT_CALL(ftrace, WriteToFile("/root/trace_clock", "global"));
model.SetupClockForTesting(config);
+ EXPECT_EQ(model.ftrace_clock(), static_cast<int>(pb0::FTRACE_CLOCK_GLOBAL));
ON_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
.WillByDefault(Return(""));
model.SetupClockForTesting(config);
+ EXPECT_EQ(model.ftrace_clock(), static_cast<int>(pb0::FTRACE_CLOCK_UNKNOWN));
ON_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
.WillByDefault(Return("local [global]"));
model.SetupClockForTesting(config);
+ EXPECT_EQ(model.ftrace_clock(), static_cast<int>(pb0::FTRACE_CLOCK_GLOBAL));
}
TEST_F(FtraceConfigMuxerTest, GetFtraceEvents) {
diff --git a/src/traced/probes/ftrace/ftrace_controller.cc b/src/traced/probes/ftrace/ftrace_controller.cc
index 0193e49..c2e8a31 100644
--- a/src/traced/probes/ftrace/ftrace_controller.cc
+++ b/src/traced/probes/ftrace/ftrace_controller.cc
@@ -249,13 +249,16 @@
// 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());
+ const auto ftrace_clock = ftrace_config_muxer_->ftrace_clock();
for (size_t i = 0; i < per_cpu_.size(); i++) {
size_t orig_quota = per_cpu_[i].period_page_quota;
if (orig_quota == 0)
continue;
size_t max_pages = std::min(orig_quota, kMaxPagesPerCpuPerReadTick);
- size_t pages_read = per_cpu_[i].reader->ReadCycle(
+ CpuReader& cpu_reader = *per_cpu_[i].reader;
+ cpu_reader.set_ftrace_clock(ftrace_clock);
+ size_t pages_read = cpu_reader.ReadCycle(
parsing_buf, kParsingBufferSizePages, max_pages, started_data_sources_);
size_t new_quota = (pages_read >= orig_quota) ? 0 : orig_quota - pages_read;
diff --git a/src/traced/probes/ftrace/ftrace_data_source.h b/src/traced/probes/ftrace/ftrace_data_source.h
index 9534763..cadcd5f 100644
--- a/src/traced/probes/ftrace/ftrace_data_source.h
+++ b/src/traced/probes/ftrace/ftrace_data_source.h
@@ -84,8 +84,11 @@
TraceWriter* trace_writer() { return writer_.get(); }
private:
+ // Hands out internal pointers to callbacks.
FtraceDataSource(const FtraceDataSource&) = delete;
FtraceDataSource& operator=(const FtraceDataSource&) = delete;
+ FtraceDataSource(FtraceDataSource&&) = delete;
+ FtraceDataSource& operator=(FtraceDataSource&&) = delete;
void WriteStats();
void DumpFtraceStats(FtraceStats*);
diff --git a/src/traced/probes/ftrace/ftrace_metadata.h b/src/traced/probes/ftrace/ftrace_metadata.h
index cdfc138..21b0530 100644
--- a/src/traced/probes/ftrace/ftrace_metadata.h
+++ b/src/traced/probes/ftrace/ftrace_metadata.h
@@ -33,7 +33,9 @@
using Inode = decltype(stat::st_ino);
// Container for tracking miscellaneous information while parsing ftrace events,
-// scoped to an individual data source.
+// scoped to an individual data source. Cleared periodically, after the metadata
+// is processed by the data sources interested in it, see
+// |OnFtraceDataWrittenIntoDataSourceBuffers|.
struct FtraceMetadata {
struct KernelAddr {
KernelAddr(uint64_t _addr, uint32_t _index) : addr(_addr), index(_index) {}
diff --git a/src/traced/probes/ftrace/ftrace_stats.h b/src/traced/probes/ftrace/ftrace_stats.h
index 1dbcbe9..ce68fe8 100644
--- a/src/traced/probes/ftrace/ftrace_stats.h
+++ b/src/traced/probes/ftrace/ftrace_stats.h
@@ -17,8 +17,7 @@
#ifndef SRC_TRACED_PROBES_FTRACE_FTRACE_STATS_H_
#define SRC_TRACED_PROBES_FTRACE_FTRACE_STATS_H_
-#include <inttypes.h>
-
+#include <cinttypes>
#include <vector>
namespace perfetto {
diff --git a/src/traced/probes/ftrace/printk_formats_parser.cc b/src/traced/probes/ftrace/printk_formats_parser.cc
index 274e981..9a36dab 100644
--- a/src/traced/probes/ftrace/printk_formats_parser.cc
+++ b/src/traced/probes/ftrace/printk_formats_parser.cc
@@ -16,9 +16,10 @@
#include "src/traced/probes/ftrace/printk_formats_parser.h"
-#include <inttypes.h>
#include <stdio.h>
+#include <cinttypes>
+
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/optional.h"
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cgroup/cgroup_attach_task/format b/src/traced/probes/ftrace/test/data/synthetic/events/cgroup/cgroup_attach_task/format
new file mode 100644
index 0000000..a0c51a8
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/synthetic/events/cgroup/cgroup_attach_task/format
@@ -0,0 +1,16 @@
+name: cgroup_attach_task
+ID: 129
+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 dst_root; offset:8; size:4; signed:1;
+ field:int dst_id; offset:12; size:4; signed:1;
+ field:int dst_level; offset:16; size:4; signed:1;
+ field:__data_loc char[] dst_path; offset:20; size:4; signed:0;
+ field:int pid; offset:24; size:4; signed:1;
+ field:__data_loc char[] comm; offset:28; size:4; signed:0;
+
+print fmt: "dst_root=%d dst_id=%d dst_level=%d dst_path=%s pid=%d comm=%s", REC->dst_root, REC->dst_id, REC->dst_level, __get_str(dst_path), REC->pid, __get_str(comm)
\ No newline at end of file
diff --git a/src/traced/probes/packages_list/packages_list_parser.h b/src/traced/probes/packages_list/packages_list_parser.h
index 9cbecd1..c294ad7 100644
--- a/src/traced/probes/packages_list/packages_list_parser.h
+++ b/src/traced/probes/packages_list/packages_list_parser.h
@@ -17,7 +17,7 @@
#ifndef SRC_TRACED_PROBES_PACKAGES_LIST_PACKAGES_LIST_PARSER_H_
#define SRC_TRACED_PROBES_PACKAGES_LIST_PACKAGES_LIST_PARSER_H_
-#include <inttypes.h>
+#include <cinttypes>
#include <string>
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..1245873 100644
--- a/src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc
+++ b/src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc
@@ -17,7 +17,6 @@
#include "perfetto/public/consumer_api.h"
#include <fcntl.h>
-#include <inttypes.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/select.h>
@@ -27,6 +26,7 @@
#include <unistd.h>
#include <atomic>
+#include <cinttypes>
#include <condition_variable>
#include <memory>
#include <mutex>
diff --git a/src/tracing/consumer_api_deprecated/consumer_api_deprecated_test.cc b/src/tracing/consumer_api_deprecated/consumer_api_deprecated_test.cc
index ebc885a..c8af35c 100644
--- a/src/tracing/consumer_api_deprecated/consumer_api_deprecated_test.cc
+++ b/src/tracing/consumer_api_deprecated/consumer_api_deprecated_test.cc
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-#include <inttypes.h>
-
#include <array>
#include <atomic>
#include <chrono>
+#include <cinttypes>
#include <thread>
#include "perfetto/base/logging.h"
diff --git a/src/tracing/core/id_allocator.cc b/src/tracing/core/id_allocator.cc
index 4b32473..f39f735 100644
--- a/src/tracing/core/id_allocator.cc
+++ b/src/tracing/core/id_allocator.cc
@@ -57,7 +57,7 @@
}
bool IdAllocatorGeneric::IsEmpty() const {
- for (const auto id : ids_) {
+ for (auto id : ids_) {
if (id)
return false;
}
diff --git a/src/tracing/core/packet_stream_validator.cc b/src/tracing/core/packet_stream_validator.cc
index 72a20f5..50d1db3 100644
--- a/src/tracing/core/packet_stream_validator.cc
+++ b/src/tracing/core/packet_stream_validator.cc
@@ -16,9 +16,10 @@
#include "src/tracing/core/packet_stream_validator.h"
-#include <inttypes.h>
#include <stddef.h>
+#include <cinttypes>
+
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/protozero/proto_utils.h"
diff --git a/src/tracing/core/trace_buffer.cc b/src/tracing/core/trace_buffer.cc
index ce6fa34..4b72d42 100644
--- a/src/tracing/core/trace_buffer.cc
+++ b/src/tracing/core/trace_buffer.cc
@@ -452,12 +452,6 @@
return false;
}
- // 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.
- char zero[Patch::kSize]{};
- PERFETTO_DCHECK(memcmp(ptr, &zero, Patch::kSize) == 0);
-
memcpy(ptr, &patches[i].data[0], Patch::kSize);
}
TRACE_BUFFER_DLOG(
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 1a5b43d..114000d 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -20,9 +20,10 @@
#include "perfetto/tracing/core/forward_decls.h"
#include <errno.h>
-#include <inttypes.h>
#include <limits.h>
#include <string.h>
+
+#include <cinttypes>
#include <regex>
#include <unordered_set>
@@ -56,6 +57,7 @@
#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"
@@ -101,16 +103,11 @@
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-// This is the only SELinux approved dir for trace files that are created
+// These are the only SELinux approved dir for trace files that are created
// directly by traced.
const char* kTraceDirBasePath = "/data/misc/perfetto-traces/";
-#endif
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-const char* kBugreportTracePath =
+const char* kAndroidProductionBugreportTracePath =
"/data/misc/perfetto-traces/bugreport/systrace.pftrace";
-#else
-const char* kBugreportTracePath = "/tmp/bugreport.pftrace";
#endif
namespace {
@@ -274,7 +271,7 @@
}
std::string GetBugreportTmpPath() {
- return std::string(kBugreportTracePath) + ".tmp";
+ return GetBugreportPath() + ".tmp";
}
bool ShouldLogEvent(const TraceConfig& cfg) {
@@ -290,6 +287,29 @@
PERFETTO_FATAL("For GCC");
}
+// Appends `data` (which has `size` bytes), to `*packet`. Splits the data in
+// slices no larger than `max_slice_size`.
+void AppendOwnedSlicesToPacket(std::unique_ptr<uint8_t[]> data,
+ size_t size,
+ size_t max_slice_size,
+ perfetto::TracePacket* packet) {
+ if (size <= max_slice_size) {
+ packet->AddSlice(Slice::TakeOwnership(std::move(data), size));
+ return;
+ }
+ uint8_t* src_ptr = data.get();
+ for (size_t size_left = size; size_left > 0;) {
+ const size_t slice_size = std::min(size_left, max_slice_size);
+
+ Slice slice = Slice::Allocate(slice_size);
+ memcpy(slice.own_data(), src_ptr, slice_size);
+ packet->AddSlice(std::move(slice));
+
+ src_ptr += slice_size;
+ size_left -= slice_size;
+ }
+}
+
} // namespace
// These constants instead are defined in the header because are used by tests.
@@ -300,6 +320,16 @@
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,
@@ -348,8 +378,8 @@
return nullptr;
}
const ProducerID id = GetNextProducerID();
- PERFETTO_DLOG("Producer %" PRIu16 " connected", id);
-
+ PERFETTO_DLOG("Producer %" PRIu16 " connected, uid=%d", id,
+ static_cast<int>(uid));
bool smb_scraping_enabled = smb_scraping_enabled_;
switch (smb_scraping_mode) {
case ProducerSMBScrapingMode::kDefault:
@@ -1825,8 +1855,9 @@
PERFETTO_DLOG("Triggering final flush for %" PRIu64, tsid);
auto weak_this = weak_ptr_factory_.GetWeakPtr();
Flush(tsid, 0, [weak_this, tsid](bool success) {
- PERFETTO_DLOG("Flush done (success: %d), disabling trace session %" PRIu64,
- success, tsid);
+ // This was a DLOG up to Jun 2021 (v16, Android S).
+ PERFETTO_LOG("FlushAndDisableTracing(%" PRIu64 ") done, success=%d", tsid,
+ success);
if (!weak_this)
return;
TracingSession* session = weak_this->GetTracingSession(tsid);
@@ -1942,7 +1973,8 @@
// 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->received_triggers.empty() &&
+ !tracing_session->seized_for_bugreport) {
PERFETTO_DLOG(
"ReadBuffers(): tracing session has not received a trigger yet.");
return false;
@@ -2159,8 +2191,9 @@
continue;
}
tracing_session->filter_output_bytes += filtered_packet.size;
- it->AddSlice(Slice::TakeOwnership(std::move(filtered_packet.data),
- filtered_packet.size));
+ AppendOwnedSlicesToPacket(std::move(filtered_packet.data),
+ filtered_packet.size, kMaxTracePacketSliceSize,
+ &*it);
} // for (packet)
} // if (trace_filter)
@@ -3190,6 +3223,12 @@
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;
@@ -3509,7 +3548,7 @@
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()));
+ producer->set_uid(static_cast<int32_t>(kv.second->uid()));
}
for (const auto& kv : service_->data_sources_) {
@@ -3540,12 +3579,12 @@
SaveTraceForBugreportCallback consumer_callback) {
PERFETTO_DCHECK_THREAD(thread_checker_);
auto on_complete_callback = [consumer_callback] {
- if (rename(GetBugreportTmpPath().c_str(), kBugreportTracePath)) {
+ if (rename(GetBugreportTmpPath().c_str(), GetBugreportPath().c_str())) {
consumer_callback(false, "rename(" + GetBugreportTmpPath() + ", " +
- kBugreportTracePath + ") failed (" +
+ GetBugreportPath() + ") failed (" +
strerror(errno) + ")");
} else {
- consumer_callback(true, kBugreportTracePath);
+ consumer_callback(true, GetBugreportPath());
}
};
if (!service_->MaybeSaveTraceForBugreport(std::move(on_complete_callback))) {
diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h
index 401aaa1..8c50713 100644
--- a/src/tracing/core/tracing_service_impl.h
+++ b/src/tracing/core/tracing_service_impl.h
@@ -77,6 +77,9 @@
static constexpr uint8_t kSyncMarker[] = {0x82, 0x47, 0x7a, 0x76, 0xb2, 0x8d,
0x42, 0xba, 0x81, 0xdc, 0x33, 0x32,
0x6d, 0x57, 0xa0, 0x79};
+ static constexpr size_t kMaxTracePacketSliceSize =
+ 128 * 1024 - 512; // This is ipc::kIPCBufferSize - 512, see assertion in
+ // tracing_integration_test.cc and b/195065199
// The implementation behind the service endpoint exposed to each producer.
class ProducerEndpointImpl : public TracingService::ProducerEndpoint {
diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
index bd4062a..a755bca 100644
--- a/src/tracing/core/tracing_service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -2331,7 +2331,8 @@
const int kNumMarkers = 5;
auto writer = producer->CreateTraceWriter("data_source");
for (int i = 1; i <= 100; i++) {
- std::string payload(static_cast<size_t>(i), 'A' + (i % 25));
+ std::string payload(static_cast<size_t>(i),
+ 'A' + static_cast<char>(i % 25));
writer->NewTracePacket()->set_for_testing()->set_str(payload.c_str());
if (i % (100 / kNumMarkers) == 0) {
writer->Flush();
@@ -3534,10 +3535,10 @@
consumer->Connect(svc.get());
std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
- producer1->Connect(svc.get(), "producer1");
+ producer1->Connect(svc.get(), "producer1", /*uid=*/0);
std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
- producer2->Connect(svc.get(), "producer2");
+ producer2->Connect(svc.get(), "producer2", /*uid=*/1002);
producer1->RegisterDataSource("common_ds");
producer2->RegisterDataSource("common_ds");
@@ -3550,8 +3551,10 @@
EXPECT_EQ(svc_state.producers_size(), 2);
EXPECT_EQ(svc_state.producers().at(0).id(), 1);
EXPECT_EQ(svc_state.producers().at(0).name(), "producer1");
+ EXPECT_EQ(svc_state.producers().at(0).uid(), 0);
EXPECT_EQ(svc_state.producers().at(1).id(), 2);
EXPECT_EQ(svc_state.producers().at(1).name(), "producer2");
+ EXPECT_EQ(svc_state.producers().at(1).uid(), 1002);
EXPECT_EQ(svc_state.data_sources_size(), 4);
diff --git a/src/tracing/internal/tracing_muxer_fake.cc b/src/tracing/internal/tracing_muxer_fake.cc
index fd4e0b5..f98c5b7 100644
--- a/src/tracing/internal/tracing_muxer_fake.cc
+++ b/src/tracing/internal/tracing_muxer_fake.cc
@@ -35,6 +35,8 @@
PERFETTO_NO_DESTROY TracingMuxerFake TracingMuxerFake::instance{};
#endif // PERFETTO_HAS_NO_DESTROY()
+TracingMuxerFake::~TracingMuxerFake() = default;
+
TracingMuxerFake::FakePlatform::~FakePlatform() = default;
Platform::ThreadLocalObject*
diff --git a/src/tracing/internal/tracing_muxer_fake.h b/src/tracing/internal/tracing_muxer_fake.h
index 0c2902b..287fdad 100644
--- a/src/tracing/internal/tracing_muxer_fake.h
+++ b/src/tracing/internal/tracing_muxer_fake.h
@@ -41,6 +41,7 @@
public:
TracingMuxerFake() : TracingMuxer(&FakePlatform::instance) {}
+ ~TracingMuxerFake() override;
static constexpr TracingMuxerFake* Get() {
#if PERFETTO_HAS_NO_DESTROY()
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index 1fb5ae8..3a4cc6d 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -697,8 +697,9 @@
instance_ = this;
// Create the thread where muxer, producers and service will live.
- task_runner_.reset(
- new NonReentrantTaskRunner(this, platform_->CreateTaskRunner({})));
+ Platform::CreateTaskRunnerArgs tr_args{/*name_for_debugging=*/"TracingMuxer"};
+ task_runner_.reset(new NonReentrantTaskRunner(
+ this, platform_->CreateTaskRunner(std::move(tr_args))));
// Run the initializer on that thread.
task_runner_->PostTask([this, args] { Initialize(args); });
diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
index e77c03f..331b2b5 100644
--- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
+++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
@@ -16,9 +16,10 @@
#include "src/tracing/ipc/consumer/consumer_ipc_client_impl.h"
-#include <inttypes.h>
#include <string.h>
+#include <cinttypes>
+
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/ipc/client.h"
#include "perfetto/ext/tracing/core/consumer.h"
diff --git a/src/tracing/ipc/default_socket.cc b/src/tracing/ipc/default_socket.cc
index 42b47e7..b210e02 100644
--- a/src/tracing/ipc/default_socket.cc
+++ b/src/tracing/ipc/default_socket.cc
@@ -47,7 +47,13 @@
// If the path doesn't exist (ENOENT), fail silently to the caller. Otherwise,
// fail with an explicit error message.
- if (errno != ENOENT) {
+ if (errno != ENOENT
+#if PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
+ // access(2) won't return EPERM, but Chromium sandbox returns EPERM if the
+ // sandbox doesn't allow the call (e.g. in the child processes).
+ && errno != EPERM
+#endif
+ ) {
PERFETTO_PLOG("%s exists but cannot be accessed. Falling back on /tmp/ ",
kRunPerfettoBaseDir);
}
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.cc b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
index 97b622c..61181d8 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.cc
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
@@ -16,7 +16,8 @@
#include "src/tracing/ipc/producer/producer_ipc_client_impl.h"
-#include <inttypes.h>
+#include <cinttypes>
+
#include <string.h>
#include "perfetto/base/logging.h"
@@ -173,13 +174,6 @@
#endif
}
-#if PERFETTO_DCHECK_IS_ON()
- req.set_build_flags(
- protos::gen::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_ON);
-#else
- 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);
diff --git a/src/tracing/ipc/service/consumer_ipc_service.cc b/src/tracing/ipc/service/consumer_ipc_service.cc
index daab5de..09b33a8 100644
--- a/src/tracing/ipc/service/consumer_ipc_service.cc
+++ b/src/tracing/ipc/service/consumer_ipc_service.cc
@@ -16,7 +16,7 @@
#include "src/tracing/ipc/service/consumer_ipc_service.h"
-#include <inttypes.h>
+#include <cinttypes>
#include "perfetto/base/logging.h"
#include "perfetto/base/task_runner.h"
diff --git a/src/tracing/ipc/service/producer_ipc_service.cc b/src/tracing/ipc/service/producer_ipc_service.cc
index 71abd8c..0e7be12 100644
--- a/src/tracing/ipc/service/producer_ipc_service.cc
+++ b/src/tracing/ipc/service/producer_ipc_service.cc
@@ -16,7 +16,7 @@
#include "src/tracing/ipc/service/producer_ipc_service.h"
-#include <inttypes.h>
+#include <cinttypes>
#include "perfetto/base/logging.h"
#include "perfetto/base/task_runner.h"
@@ -84,17 +84,6 @@
break;
}
-#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.
- }
-#endif
-
// If the producer provided an SMB, tell the service to attempt to adopt it.
std::unique_ptr<SharedMemory> shmem;
if (req.producer_provided_shmem()) {
diff --git a/src/tracing/platform_posix.cc b/src/tracing/platform_posix.cc
index d6413ee..cf2bcff 100644
--- a/src/tracing/platform_posix.cc
+++ b/src/tracing/platform_posix.cc
@@ -89,9 +89,9 @@
}
std::unique_ptr<base::TaskRunner> PlatformPosix::CreateTaskRunner(
- const CreateTaskRunnerArgs&) {
- return std::unique_ptr<base::TaskRunner>(
- new base::ThreadTaskRunner(base::ThreadTaskRunner::CreateAndStart()));
+ const CreateTaskRunnerArgs& args) {
+ return std::unique_ptr<base::TaskRunner>(new base::ThreadTaskRunner(
+ base::ThreadTaskRunner::CreateAndStart(args.name_for_debugging)));
}
std::string PlatformPosix::GetCurrentProcessName() {
diff --git a/src/tracing/platform_windows.cc b/src/tracing/platform_windows.cc
index f5db52d..0f1664c 100644
--- a/src/tracing/platform_windows.cc
+++ b/src/tracing/platform_windows.cc
@@ -96,9 +96,9 @@
}
std::unique_ptr<base::TaskRunner> PlatformWindows::CreateTaskRunner(
- const CreateTaskRunnerArgs&) {
- return std::unique_ptr<base::TaskRunner>(
- new base::ThreadTaskRunner(base::ThreadTaskRunner::CreateAndStart()));
+ const CreateTaskRunnerArgs& args) {
+ return std::unique_ptr<base::TaskRunner>(new base::ThreadTaskRunner(
+ base::ThreadTaskRunner::CreateAndStart(args.name_for_debugging)));
}
std::string PlatformWindows::GetCurrentProcessName() {
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 5e93578..50b1463 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -3453,6 +3453,20 @@
// Metadata event.
TRACE_EVENT_METADATA1("cat", "LegacyMetadata", "obsolete", true);
+ // Async events.
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP_AND_FLAGS0(
+ "cat", "LegacyAsync", 5678, MyTimestamp{4}, TRACE_EVENT_FLAG_NONE);
+ TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0("cat", "LegacyAsync", 5678,
+ MyTimestamp{5});
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_FLAGS0("cat", "LegacyAsync2", 9000,
+ TRACE_EVENT_FLAG_NONE);
+ TRACE_EVENT_NESTABLE_ASYNC_END_WITH_FLAGS0("cat", "LegacyAsync2", 9000,
+ TRACE_EVENT_FLAG_NONE);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_FLAGS0("cat", "LegacyAsync3", 9001,
+ TRACE_EVENT_FLAG_NONE);
+ TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP_AND_FLAGS0(
+ "cat", "LegacyAsync3", 9001, MyTimestamp{6}, TRACE_EVENT_FLAG_NONE);
+
perfetto::TrackEvent::Flush();
tracing_session->get()->StopBlocking();
auto slices = ReadSlicesFromTrace(tracing_session->get());
@@ -3470,7 +3484,13 @@
"]Legacy_S(unscoped_id=1):cat.LegacyWithIdTidAndTimestamp",
"Legacy_C:cat.LegacyCounter(value=(int)1234)",
"Legacy_C(unscoped_id=1234):cat.LegacyCounterWithId(value=(int)9000)",
- "Legacy_M:cat.LegacyMetadata"));
+ "Legacy_M:cat.LegacyMetadata",
+ "Legacy_b(unscoped_id=5678):cat.LegacyAsync",
+ "Legacy_e(unscoped_id=5678):cat.LegacyAsync",
+ "Legacy_b(unscoped_id=9000):cat.LegacyAsync2",
+ "Legacy_e(unscoped_id=9000):cat.LegacyAsync2",
+ "Legacy_b(unscoped_id=9001):cat.LegacyAsync3",
+ "Legacy_e(unscoped_id=9001):cat.LegacyAsync3"));
}
TEST_P(PerfettoApiTest, LegacyTraceEventsWithCustomAnnotation) {
@@ -4145,6 +4165,35 @@
"Voltage = 220", "Power = 1.21"));
}
+TEST_P(PerfettoApiTest, EmptyEvent) {
+ auto* tracing_session = NewTraceWithCategories({"cat"});
+ tracing_session->get()->StartBlocking();
+
+ // Emit an empty event.
+ PERFETTO_INTERNAL_ADD_EMPTY_EVENT();
+ 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()));
+ auto it = std::find_if(trace.packet().begin(), trace.packet().end(),
+ [](const perfetto::protos::gen::TracePacket& packet) {
+ return packet.has_trace_stats();
+ });
+ EXPECT_NE(it, trace.packet().end());
+ // The empty event required a trace chunk.
+ EXPECT_EQ(it->trace_stats().buffer_stats()[0].chunks_read(), 1u);
+ // But it isn't in the trace, because empty packets are skipped when reading
+ // from TraceBuffer.
+ it = std::find_if(trace.packet().begin(), trace.packet().end(),
+ [](const perfetto::protos::gen::TracePacket& packet) {
+ return packet.has_track_event();
+ });
+ EXPECT_EQ(it, trace.packet().end());
+}
+
struct BackendTypeAsString {
std::string operator()(
const ::testing::TestParamInfo<perfetto::BackendType>& info) const {
diff --git a/src/tracing/test/tracing_integration_test.cc b/src/tracing/test/tracing_integration_test.cc
index 3fc8d4b..d1ca340 100644
--- a/src/tracing/test/tracing_integration_test.cc
+++ b/src/tracing/test/tracing_integration_test.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <inttypes.h>
+#include <cinttypes>
#include "perfetto/ext/base/temp_file.h"
#include "perfetto/ext/tracing/core/consumer.h"
@@ -113,6 +113,11 @@
EXPECT_EQ(0u, buf_stats.abi_violations());
}
+static_assert(TracingServiceImpl::kMaxTracePacketSliceSize <=
+ ipc::kIPCBufferSize - 512,
+ "Tracing service max packet slice should be smaller than IPC "
+ "buffer size (with some headroom)");
+
} // namespace
class TracingIntegrationTest : public ::testing::Test {
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 64e683a..01ae3c6 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -41,6 +41,7 @@
]
if (enable_perfetto_traced_probes) {
deps += [
+ "../src/protozero/filtering:bytecode_generator",
"../src/traced/probes/ftrace",
"../src/traced/probes/ftrace:ftrace_procfs",
]
diff --git a/test/ci/ui_tests.sh b/test/ci/ui_tests.sh
index 9a1fa3a..619d0f2 100755
--- a/test/ci/ui_tests.sh
+++ b/test/ci/ui_tests.sh
@@ -16,8 +16,18 @@
INSTALL_BUILD_DEPS_ARGS="--ui"
source $(dirname ${BASH_SOURCE[0]})/common.sh
-tools/node ui/build.js --out ${OUT_PATH}
+ui/build --out ${OUT_PATH}
cp -a ${OUT_PATH}/ui/dist/ /ci/artifacts/ui
-tools/node ui/build.js --out ${OUT_PATH} --no-build --run-tests
+ui/run-unittests --out ${OUT_PATH} --no-build
+
+set +e
+ui/run-integrationtests --out ${OUT_PATH} --no-build
+RES=$?
+
+# Copy the screenshots for diff testing when the test fails.
+if [ $RES -ne 0 -a -d ${OUT_PATH}/ui-test-artifacts ]; then
+ cp -a ${OUT_PATH}/ui-test-artifacts /ci/artifacts/ui-test-artifacts
+ exit $RES
+fi
diff --git a/test/cts/heapprofd_test_cts.cc b/test/cts/heapprofd_test_cts.cc
index 2215517..69aa344 100644
--- a/test/cts/heapprofd_test_cts.cc
+++ b/test/cts/heapprofd_test_cts.cc
@@ -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;
diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc
index 435690d..1ec13d3 100644
--- a/test/end_to_end_integrationtest.cc
+++ b/test/end_to_end_integrationtest.cc
@@ -41,6 +41,7 @@
#include "perfetto/tracing/core/tracing_service_state.h"
#include "src/base/test/test_task_runner.h"
#include "src/base/test/utils.h"
+#include "src/protozero/filtering/filter_bytecode_generator.h"
#include "src/traced/probes/ftrace/ftrace_controller.h"
#include "src/traced/probes/ftrace/ftrace_procfs.h"
#include "test/gtest_and_gmock.h"
@@ -74,8 +75,11 @@
namespace {
using ::testing::ContainsRegex;
+using ::testing::Each;
using ::testing::ElementsAreArray;
using ::testing::HasSubstr;
+using ::testing::Property;
+using ::testing::SizeIs;
std::string RandomTraceFileName() {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
@@ -271,7 +275,7 @@
// 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(kBugreportTracePath, &trace_str);
+ base::ReadFile(GetBugreportPath(), &trace_str);
ASSERT_FALSE(trace_str.empty());
protos::gen::Trace trace;
ASSERT_TRUE(trace.ParseFromString(trace_str));
@@ -977,7 +981,8 @@
DataSourceDescriptor dsd;
std::string name = "big_ds_" + std::to_string(i);
dsd.set_name(name);
- std::string descriptor(ipc::kIPCBufferSize - 64, (' ' + i) % 64);
+ std::string descriptor(ipc::kIPCBufferSize - 64,
+ static_cast<char>((' ' + i) % 64));
dsd.set_track_event_descriptor_raw(descriptor);
ds_expected[name] = std::move(descriptor);
producer->RegisterDataSource(dsd);
@@ -1077,6 +1082,114 @@
}
}
+// 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());
+ }
+}
+
+// Regression test for b/195065199. Check that trace filtering works when a
+// packet size exceeds the IPC limit. This tests that the tracing service, when
+// reassembling packets after filtering, doesn't "overglue" them. They still
+// need to be slice-able to fit into the ReadBuffers ipc.
+TEST_F(PerfettoTest, TraceFilterLargePackets) {
+ base::TestTaskRunner task_runner;
+ TestHelper helper(&task_runner);
+
+ helper.StartServiceIfRequired();
+ helper.ConnectFakeProducer();
+ helper.ConnectConsumer();
+ helper.WaitForConsumerConnect();
+
+ TraceConfig trace_config;
+ trace_config.add_buffers()->set_size_kb(1024 * 16);
+ trace_config.set_duration_ms(500);
+ auto* prod_config = trace_config.add_producers();
+ prod_config->set_producer_name("android.perfetto.FakeProducer");
+ prod_config->set_shm_size_kb(1024 * 16);
+ prod_config->set_page_size_kb(32);
+
+ static constexpr size_t kNumPackets = 3;
+ static constexpr uint32_t kRandomSeed = 42;
+ static constexpr uint32_t kMsgSize = 8 * ipc::kIPCBufferSize;
+ auto* ds_config = trace_config.add_data_sources()->mutable_config();
+ ds_config->set_name("android.perfetto.FakeProducer");
+ auto* test_config = ds_config->mutable_for_testing();
+ test_config->set_seed(kRandomSeed);
+ test_config->set_message_count(kNumPackets);
+ test_config->set_message_size(kMsgSize);
+ test_config->set_send_batch_on_register(true);
+
+ protozero::FilterBytecodeGenerator filt;
+ // Message 0: root Trace proto.
+ filt.AddNestedField(1 /* root trace.packet*/, 1);
+ filt.EndMessage();
+
+ // Message 1: TracePacket proto. Allow all fields.
+ filt.AddSimpleFieldRange(1, 1000);
+ filt.EndMessage();
+
+ trace_config.mutable_trace_filter()->set_bytecode(filt.Serialize());
+
+ // The data source is configured to emit another batch when it is started via
+ // send_batch_on_register in the TestConfig.
+ helper.StartTracing(trace_config);
+ helper.WaitForTracingDisabled();
+
+ helper.ReadData();
+ helper.WaitForReadData(/* read_count */ 0, /* timeout_ms */ 10000);
+
+ const std::vector<protos::gen::TracePacket>& packets = helper.trace();
+ EXPECT_EQ(packets.size(), kNumPackets);
+ EXPECT_THAT(packets,
+ Each(Property(&protos::gen::TracePacket::has_for_testing, true)));
+ EXPECT_THAT(
+ packets,
+ Each(Property(&protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str, SizeIs(kMsgSize)))));
+}
+
// 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 ).
diff --git a/test/synth_common.py b/test/synth_common.py
index 0cf5fdd..d8c39fc 100644
--- a/test/synth_common.py
+++ b/test/synth_common.py
@@ -214,6 +214,35 @@
battery_count.current_ua = curr_ua
battery_count.current_avg_ua = curr_avg_ua
+ def add_binder_transaction(self, transaction_id, ts_start, ts_end, tid, pid,
+ reply_id, reply_ts_start, reply_ts_end, reply_tid,
+ reply_pid):
+ # Binder transaction start.
+ ftrace = self.__add_ftrace_event(ts_start, tid)
+ binder_transaction = ftrace.binder_transaction
+ binder_transaction.debug_id = transaction_id
+ binder_transaction.to_proc = reply_pid
+ binder_transaction.to_thread = reply_tid
+ binder_transaction.reply = False
+
+ # Binder reply start
+ ftrace = self.__add_ftrace_event(reply_ts_start, reply_tid)
+ binder_transaction_received = ftrace.binder_transaction_received
+ binder_transaction_received.debug_id = transaction_id
+
+ # Binder reply finish
+ ftrace = self.__add_ftrace_event(reply_ts_end, reply_tid)
+ reply_binder_transaction = ftrace.binder_transaction
+ reply_binder_transaction.debug_id = reply_id
+ reply_binder_transaction.to_proc = pid
+ reply_binder_transaction.to_thread = tid
+ reply_binder_transaction.reply = True
+
+ # Binder transaction finish
+ ftrace = self.__add_ftrace_event(ts_end, tid)
+ reply_binder_transaction_received = ftrace.binder_transaction_received
+ reply_binder_transaction_received.debug_id = reply_id
+
def add_battery_counters_no_curr_ua(self, ts, charge_uah, cap_prct,
curr_avg_ua):
self.packet = self.trace.packet.add()
@@ -404,8 +433,8 @@
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)
+ def add_gpu_mem_total_ftrace_event(self, ftrace_pid, pid, ts, size):
+ ftrace = self.__add_ftrace_event(ts, ftrace_pid)
gpu_mem_total_ftrace_event = ftrace.gpu_mem_total
gpu_mem_total_ftrace_event.pid = pid
gpu_mem_total_ftrace_event.size = size
@@ -616,6 +645,7 @@
track=None,
trusted_sequence_id=None,
trace_id=None,
+ step=None,
flow_ids=[],
terminating_flow_ids=[]):
packet = self.add_track_event_slice(
@@ -626,6 +656,8 @@
trusted_sequence_id=trusted_sequence_id)
if trace_id is not None:
packet.track_event.chrome_latency_info.trace_id = trace_id
+ if step is not None:
+ packet.track_event.chrome_latency_info.step = step
for flow_id in flow_ids:
packet.track_event.flow_ids.append(flow_id)
for flow_id in terminating_flow_ids:
@@ -639,13 +671,24 @@
track=None,
trace_id=None,
gesture_scroll_id=None,
- is_coalesced=None):
+ touch_id=None,
+ is_coalesced=None,
+ gets_to_gpu=True):
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
+ latency_info = packet.track_event.chrome_latency_info
+ latency_info.trace_id = trace_id
+ if gesture_scroll_id is not None:
+ latency_info.gesture_scroll_id = gesture_scroll_id
+ if touch_id is not None:
+ latency_info.touch_id = touch_id
+ if gets_to_gpu:
+ component = latency_info.component_info.add()
+ component.component_type = self.prototypes \
+ .ChromeLatencyInfo.ComponentType \
+ .COMPONENT_INPUT_EVENT_GPU_SWAP_BUFFER
if is_coalesced is not None:
- packet.track_event.chrome_latency_info.is_coalesced = is_coalesced
+ latency_info.is_coalesced = is_coalesced
return packet
def add_chrome_metadata(self, os_name=None):
@@ -667,7 +710,8 @@
def add_actual_display_frame_start_event(self, ts, cookie, token, pid,
present_type, on_time_finish,
- gpu_composition, jank_type, prediction_type):
+ gpu_composition, jank_type,
+ prediction_type):
packet = self.add_packet()
packet.timestamp = ts
event = packet.frame_timeline_event.actual_display_frame_start
@@ -697,7 +741,8 @@
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):
+ gpu_composition, jank_type,
+ prediction_type):
packet = self.add_packet()
packet.timestamp = ts
event = packet.frame_timeline_event.actual_surface_frame_start
@@ -759,24 +804,40 @@
setattr(res, desc.name, desc.number)
return res
+ ChromeLatencyInfo = namedtuple('ChromeLatencyInfo', [
+ 'ComponentType',
+ 'Step',
+ ])
+
Prototypes = namedtuple('Prototypes', [
'TrackEvent',
'ChromeRAILMode',
- 'ThreadDescriptor',
+ 'ChromeLatencyInfo',
'ChromeProcessDescriptor',
'CounterDescriptor',
+ 'ThreadDescriptor',
])
+
+ chrome_latency_info_prototypes = ChromeLatencyInfo(
+ ComponentType=EnumPrototype.from_descriptor(
+ pool.FindEnumTypeByName(
+ 'perfetto.protos.ChromeLatencyInfo.LatencyComponentType')),
+ Step=EnumPrototype.from_descriptor(
+ pool.FindEnumTypeByName('perfetto.protos.ChromeLatencyInfo.Step')),
+ )
+
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')),
+ ChromeLatencyInfo=chrome_latency_info_prototypes,
ChromeProcessDescriptor=factory.GetPrototype(
pool.FindMessageTypeByName(
'perfetto.protos.ChromeProcessDescriptor')),
CounterDescriptor=factory.GetPrototype(
pool.FindMessageTypeByName('perfetto.protos.CounterDescriptor')),
+ ThreadDescriptor=factory.GetPrototype(
+ pool.FindMessageTypeByName('perfetto.protos.ThreadDescriptor')),
)
return Trace(ProtoTrace(), prototypes)
diff --git a/test/trace_processor/chrome/index b/test/trace_processor/chrome/index
index 5466346..3ba13d8 100644
--- a/test/trace_processor/chrome/index
+++ b/test/trace_processor/chrome/index
@@ -1,6 +1,8 @@
# Tests related to Chrome's use of Perfetto.
# Chrome metrics (found in the trace_processor/chrome directory).
+
+# Scroll jank metrics
../../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
@@ -14,6 +16,15 @@
../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
+scroll_jank_gpu_check.py scroll_jank_gpu_check.sql scroll_jank_gpu_check.out
+
+# Touch gesture metrics
+../../data/chrome_touch_gesture_scroll.pftrace touch_jank.sql touch_jank.out
+../../data/chrome_touch_gesture_scroll.pftrace touch_flow_event.sql touch_flow_event.out
+../../data/chrome_touch_gesture_scroll.pftrace touch_flow_event_queuing_delay.sql touch_flow_event_queuing_delay.out
+touch_jank.py touch_jank.sql touch_jank_synth.out
+touch_jank.py touch_flow_event.sql touch_flow_event_synth.out
+touch_jank.py touch_flow_event_queuing_delay_full.sql touch_flow_event_queuing_delay_synth.out
# Chrome memory snapshots.
../../data/chrome_memory_snapshot.pftrace memory_snapshot_general_validation.sql memory_snapshot_general_validation.out
diff --git a/test/trace_processor/chrome/scroll_flow_event.out b/test/trace_processor/chrome/scroll_flow_event.out
index 569ae86..148f46b 100644
--- a/test/trace_processor/chrome/scroll_flow_event.out
+++ b/test/trace_processor/chrome/scroll_flow_event.out
@@ -48,14 +48,14 @@
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"
+2725,545024000403,31889426,0,"AsyncBegin",545024000403,545025279403,545025586403,2725,"Begin"
+2725,545025586403,2000,0,"Begin",545025746403,545025279403,545025615403,2725,"STEP_SEND_INPUT_EVENT_UI"
+2725,545025615403,117000,0,"STEP_SEND_INPUT_EVENT_UI",545025746403,545025698611,545025703611,2725,"STEP_HANDLE_INPUT_EVENT_IMPL"
+2725,545025703611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545025713611,545033251611,545033256611,2725,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+2725,545033256611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545033344611,545034007611,545034007611,2725,"STEP_SWAP_BUFFERS"
+2725,545034007611,5000,0,"STEP_SWAP_BUFFERS",545034012611,545047703829,545047703829,2725,"STEP_DRAW_AND_SWAP"
+2725,545047703829,1000,0,"STEP_DRAW_AND_SWAP",545047704829,545055892829,545055892829,2725,"End"
+2725,545055892829,1000,0,"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"
@@ -752,14 +752,14 @@
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"
+2960,546200000403,40097426,0,"AsyncBegin",546200000403,546201377403,546201519403,2960,"Begin"
+2960,546201519403,1000,0,"Begin",546201586403,546201377403,546201544403,2960,"STEP_SEND_INPUT_EVENT_UI"
+2960,546201544403,31000,0,"STEP_SEND_INPUT_EVENT_UI",546201586403,546201665611,546201667611,2960,"STEP_HANDLE_INPUT_EVENT_IMPL"
+2960,546201667611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546201677611,546205643611,546205647611,2960,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+2960,546205647611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546205696611,546206945611,546206945611,2960,"STEP_SWAP_BUFFERS"
+2960,546206945611,8000,0,"STEP_SWAP_BUFFERS",546206953611,546220078829,546220078829,2960,"STEP_DRAW_AND_SWAP"
+2960,546220078829,1000,0,"STEP_DRAW_AND_SWAP",546220079829,546240099829,546240099829,2960,"End"
+2960,546240099829,1000,0,"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"
diff --git a/test/trace_processor/chrome/scroll_flow_event_general_validation.out b/test/trace_processor/chrome/scroll_flow_event_general_validation.out
index 295637e..5a223bf 100644
--- a/test/trace_processor/chrome/scroll_flow_event_general_validation.out
+++ b/test/trace_processor/chrome/scroll_flow_event_general_validation.out
@@ -1,3 +1,3 @@
"total_scroll_updates","total_flow_event_steps","total_janky_flow_event_steps","number_of_unique_steps"
-139,1112,72,8
+139,1112,56,8
diff --git a/test/trace_processor/chrome/scroll_flow_event_queuing_delay.out b/test/trace_processor/chrome/scroll_flow_event_queuing_delay.out
index 610f04b..519e25c 100644
--- a/test/trace_processor/chrome/scroll_flow_event_queuing_delay.out
+++ b/test/trace_processor/chrome/scroll_flow_event_queuing_delay.out
@@ -1,26 +1,26 @@
-"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]"
+"trace_id","jank","step","next_step","ancestor_end","maybe_next_ancestor_ts","queuing_time_ns"
+2954,0,"AsyncBegin","Begin",546175000403,546176663403,1663000
+2954,0,"Begin","STEP_SEND_INPUT_EVENT_UI",546176884403,546176663403,0
+2954,0,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",546176884403,546176948611,64208
+2954,0,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546176961611,546183503611,6542000
+2954,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_SWAP_BUFFERS",546183547611,546184802611,1255000
+2954,0,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",546184809611,546186327829,1518218
+2954,0,"STEP_DRAW_AND_SWAP","End",546186335829,546205976829,19641000
+2954,0,"End","AsyncBegin",546205978829,"[NULL]","[NULL]"
+2956,1,"AsyncBegin","Begin",546183000403,546186878403,3878000
+2956,1,"Begin","STEP_SEND_INPUT_EVENT_UI",546187103403,546186878403,0
+2956,1,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",546187103403,546187138611,35208
+2956,1,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546187149611,546194427611,7278000
+2956,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_SWAP_BUFFERS",546194464611,546195772611,1308000
+2956,1,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",546195778611,546207402829,11624218
+2956,1,"STEP_DRAW_AND_SWAP","End",546207409829,546228297829,20888000
+2956,1,"End","AsyncBegin",546228304829,"[NULL]","[NULL]"
+2960,0,"AsyncBegin","Begin",546200000403,546201377403,1377000
+2960,0,"Begin","STEP_SEND_INPUT_EVENT_UI",546201586403,546201377403,0
+2960,0,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",546201586403,546201665611,79208
+2960,0,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546201677611,546205643611,3966000
+2960,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_SWAP_BUFFERS",546205696611,546206945611,1249000
+2960,0,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",546206953611,546220078829,13125218
+2960,0,"STEP_DRAW_AND_SWAP","End",546220079829,546240099829,20020000
+2960,0,"End","AsyncBegin",546240100829,"[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
index fdbb40c..50e79b8 100644
--- a/test/trace_processor/chrome/scroll_flow_event_queuing_delay.sql
+++ b/test/trace_processor/chrome/scroll_flow_event_queuing_delay.sql
@@ -16,15 +16,16 @@
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
+-- trace 2956 is janky and 2954 and 2960 surround it (both are not janky). We
-- just manually computed these values to ensure the queuing time is correct.
SELECT
trace_id,
+ jank,
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
+WHERE trace_id = 2954 OR trace_id = 2956 OR trace_id = 2960
ORDER BY trace_id, ts;
diff --git a/test/trace_processor/chrome/scroll_jank.out b/test/trace_processor/chrome/scroll_jank.out
index fb1120f..baaa642 100644
--- a/test/trace_processor/chrome/scroll_jank.out
+++ b/test/trace_processor/chrome/scroll_jank.out
@@ -6,7 +6,7 @@
2708,2717,0,544991000403,30714426
2708,2719,0,544999000403,34740426
2708,2721,0,545007000403,37462426
-2708,2725,1,545024000403,31889426
+2708,2725,0,545024000403,31889426
2708,2727,0,545032000403,23876426
2708,2729,0,545040000403,28316426
2708,2733,0,545056000403,22620426
@@ -94,7 +94,7 @@
2917,2950,0,546159000403,35994426
2917,2954,0,546175000403,30970426
2917,2956,1,546183000403,45256426
-2917,2960,1,546200000403,40097426
+2917,2960,0,546200000403,40097426
2917,2962,0,546208000403,32086426
2917,2964,0,546216000403,34686426
2917,2968,0,546233000403,28852426
diff --git a/test/trace_processor/chrome/scroll_jank_cause.out b/test/trace_processor/chrome/scroll_jank_cause.out
index 06ced33..c8d577e 100644
--- a/test/trace_processor/chrome/scroll_jank_cause.out
+++ b/test/trace_processor/chrome/scroll_jank_cause.out
@@ -1,3 +1,3 @@
"total","total_jank","sum_explained_and_unexplained","error_rows"
-139,9,9,0
+139,7,7,0
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
index 48fe6de..7e3393f 100644
--- 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
@@ -1,3 +1,3 @@
"total","janky_latency_info_non_jank_avg_dur","non_janky_latency_info_non_jank_avg_dur"
-139,6387.096774,6387.096774
+139,6358.208955,6358.208955
diff --git a/test/trace_processor/chrome/scroll_jank_general_validation.out b/test/trace_processor/chrome/scroll_jank_general_validation.out
index d4323b2..d76d3bc 100644
--- a/test/trace_processor/chrome/scroll_jank_general_validation.out
+++ b/test/trace_processor/chrome/scroll_jank_general_validation.out
@@ -1,3 +1,3 @@
"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
+2,1628470852,139,3974685214,7,310070982,7,16666666.666667
diff --git a/test/trace_processor/chrome/scroll_jank_general_validation.sql b/test/trace_processor/chrome/scroll_jank_general_validation.sql
index 4143875..1aa3059 100644
--- a/test/trace_processor/chrome/scroll_jank_general_validation.sql
+++ b/test/trace_processor/chrome/scroll_jank_general_validation.sql
@@ -34,7 +34,7 @@
-- 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
+ gesture_scroll_id, max(maybe_gesture_end) - begin_ts AS scroll_dur
FROM scroll_jank
GROUP BY gesture_scroll_id
)
diff --git a/test/trace_processor/chrome/scroll_jank_gpu_check.out b/test/trace_processor/chrome/scroll_jank_gpu_check.out
new file mode 100644
index 0000000..f5dad3d
--- /dev/null
+++ b/test/trace_processor/chrome/scroll_jank_gpu_check.out
@@ -0,0 +1,5 @@
+
+"ts","jank"
+15000000,0
+30000000,1
+115000000,0
diff --git a/test/trace_processor/chrome/scroll_jank_gpu_check.py b/test/trace_processor/chrome/scroll_jank_gpu_check.py
new file mode 100644
index 0000000..7e33ac2
--- /dev/null
+++ b/test/trace_processor/chrome/scroll_jank_gpu_check.py
@@ -0,0 +1,86 @@
+#!/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.
+
+# Discarded events that do not get to GPU are invisible for UMA metric and
+# therefore should be excluded in trace-based metric. This tests ensures that's
+# the case.
+
+from os import sys
+
+import synth_common
+
+from synth_common import ms_to_ns
+trace = synth_common.create_trace()
+
+
+class Helper:
+
+ def __init__(self, trace, start_id, start_gesture_id):
+ self.trace = trace
+ self.id = start_id
+ self.gesture_id = start_gesture_id
+
+ def begin(self, from_ms, dur_ms):
+ self.trace.add_input_latency_event_slice(
+ "GestureScrollBegin",
+ ts=ms_to_ns(from_ms),
+ dur=ms_to_ns(dur_ms),
+ track=self.id,
+ trace_id=self.id,
+ gesture_scroll_id=self.gesture_id,
+ )
+ self.id += 1
+
+ def update(self, from_ms, dur_ms, gets_to_gpu=True):
+ self.trace.add_input_latency_event_slice(
+ "GestureScrollUpdate",
+ ts=ms_to_ns(from_ms),
+ dur=ms_to_ns(dur_ms),
+ track=self.id,
+ trace_id=self.id,
+ gesture_scroll_id=self.gesture_id,
+ gets_to_gpu=gets_to_gpu,
+ is_coalesced=False,
+ )
+ self.id += 1
+
+ def end(self, from_ms, dur_ms):
+ self.trace.add_input_latency_event_slice(
+ "GestureScrollEnd",
+ ts=ms_to_ns(from_ms),
+ dur=ms_to_ns(dur_ms),
+ track=self.id,
+ trace_id=self.id,
+ gesture_scroll_id=self.gesture_id)
+ self.id += 1
+ self.gesture_id += 1
+
+
+helper = Helper(trace, start_id=1234, start_gesture_id=5678)
+
+helper.begin(from_ms=0, dur_ms=10)
+helper.update(from_ms=15, dur_ms=10)
+# The next update should be recognized as janky
+helper.update(from_ms=30, dur_ms=30)
+helper.end(from_ms=70, dur_ms=10)
+
+helper.begin(from_ms=100, dur_ms=10)
+helper.update(from_ms=115, dur_ms=10)
+# The next update doesn't get to GPU, therefore would not be a part of jank
+# calculation
+helper.update(from_ms=130, dur_ms=30, gets_to_gpu=False)
+helper.end(from_ms=170, dur_ms=10)
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/scroll_jank_gpu_check.sql b/test/trace_processor/chrome/scroll_jank_gpu_check.sql
new file mode 100644
index 0000000..d3740b5
--- /dev/null
+++ b/test/trace_processor/chrome/scroll_jank_gpu_check.sql
@@ -0,0 +1,20 @@
+--
+-- 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.sql') AS suppress_query_output;
+
+SELECT ts, jank
+FROM scroll_jank
+ORDER BY ts ASC;
diff --git a/test/trace_processor/chrome/touch_flow_event.out b/test/trace_processor/chrome/touch_flow_event.out
new file mode 100644
index 0000000..ae13efd
--- /dev/null
+++ b/test/trace_processor/chrome/touch_flow_event.out
@@ -0,0 +1,170 @@
+
+"trace_id","ts","dur","jank","step","ancestor_end","maybe_next_ancestor_ts","next_ts","next_trace_id","next_step"
+6288,1383122421558418,226350000,1,"AsyncBegin",1383122421558418,1383122426402418,1383122426484418,6288,"Begin"
+6288,1383122426484418,11000,1,"Begin",1383122426884418,1383122426402418,1383122426625418,6288,"STEP_SEND_INPUT_EVENT_UI"
+6288,1383122426625418,237000,1,"STEP_SEND_INPUT_EVENT_UI",1383122426884418,1383122427140418,1383122427169418,6288,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6288,1383122427169418,163000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383122427336418,1383122427140418,1383122427275418,6288,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6288,1383122427275418,5000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383122427336418,1383122456261418,1383122456261418,6288,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6288,1383122456261418,37514000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383122493775418,1383122456261418,1383122493472418,6288,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6288,1383122493472418,10000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383122493775418,1383122496371418,1383122496371418,6288,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6288,1383122496371418,7000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383122496378418,1383122589999418,1383122589999418,6288,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6288,1383122589999418,24000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383122590023418,1383122601085418,1383122601085418,6288,"STEP_SWAP_BUFFERS"
+6288,1383122601085418,19000,1,"STEP_SWAP_BUFFERS",1383122601104418,1383122611053418,1383122611053418,6288,"STEP_DRAW_AND_SWAP"
+6288,1383122611053418,88000,1,"STEP_DRAW_AND_SWAP",1383122611141418,1383122647945418,1383122647945418,6288,"STEP_FINISHED_SWAP_BUFFERS"
+6288,1383122647945418,100000,1,"STEP_FINISHED_SWAP_BUFFERS",1383122648045418,"[NULL]",1383122543558418,6312,"AsyncBegin"
+6312,1383122543558418,185244000,0,"AsyncBegin",1383122543558418,1383122548583418,1383122548633418,6312,"Begin"
+6312,1383122548633418,6000,0,"Begin",1383122548862418,1383122548583418,1383122548703418,6312,"STEP_SEND_INPUT_EVENT_UI"
+6312,1383122548703418,148000,0,"STEP_SEND_INPUT_EVENT_UI",1383122548862418,1383122550407418,1383122550456418,6312,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6312,1383122550456418,364000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383122550827418,1383122550407418,1383122550719418,6312,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6312,1383122550719418,10000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383122550827418,1383122591844418,1383122591844418,6312,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6312,1383122591844418,9681000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383122601525418,1383122591844418,1383122601331418,6312,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6312,1383122601331418,9000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383122601525418,1383122603068418,1383122603068418,6312,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6312,1383122603068418,16000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383122603084418,1383122667027418,1383122667027418,6312,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6312,1383122667027418,18000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383122667045418,1383122676422418,1383122676422418,6312,"STEP_SWAP_BUFFERS"
+6312,1383122676422418,18000,0,"STEP_SWAP_BUFFERS",1383122676440418,1383122688317418,1383122688317418,6312,"STEP_DRAW_AND_SWAP"
+6312,1383122688317418,30000,0,"STEP_DRAW_AND_SWAP",1383122688347418,1383122728832418,1383122728832418,6312,"STEP_FINISHED_SWAP_BUFFERS"
+6312,1383122728832418,24000,0,"STEP_FINISHED_SWAP_BUFFERS",1383122728856418,"[NULL]",1383123604558418,6328,"AsyncBegin"
+6328,1383123604558418,207945000,1,"AsyncBegin",1383123604558418,1383123610384418,1383123610436418,6328,"Begin"
+6328,1383123610436418,7000,1,"Begin",1383123610707418,1383123610384418,1383123610515418,6328,"STEP_SEND_INPUT_EVENT_UI"
+6328,1383123610515418,181000,1,"STEP_SEND_INPUT_EVENT_UI",1383123610707418,1383123611090418,1383123611121418,6328,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6328,1383123611121418,262000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383123611387418,1383123611090418,1383123611283418,6328,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6328,1383123611283418,11000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383123611387418,1383123645509418,1383123645509418,6328,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6328,1383123645509418,9318000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383123654827418,1383123645509418,1383123654631418,6328,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6328,1383123654631418,8000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383123654827418,1383123656978418,1383123656978418,6328,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6328,1383123656978418,30000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383123657008418,1383123762642418,1383123762642418,6328,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6328,1383123762642418,13000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383123762655418,1383123768318418,1383123768318418,6328,"STEP_SWAP_BUFFERS"
+6328,1383123768318418,14000,1,"STEP_SWAP_BUFFERS",1383123768332418,1383123774132418,1383123774132418,6328,"STEP_DRAW_AND_SWAP"
+6328,1383123774132418,28000,1,"STEP_DRAW_AND_SWAP",1383123774160418,1383123812534418,1383123812534418,6328,"STEP_FINISHED_SWAP_BUFFERS"
+6328,1383123812534418,19000,1,"STEP_FINISHED_SWAP_BUFFERS",1383123812553418,"[NULL]",1383124088558418,6414,"AsyncBegin"
+6414,1383124088558418,173233000,0,"AsyncBegin",1383124088558418,1383124093797418,1383124093844418,6414,"Begin"
+6414,1383124093844418,6000,0,"Begin",1383124094081418,1383124093797418,1383124093918418,6414,"STEP_SEND_INPUT_EVENT_UI"
+6414,1383124093918418,153000,0,"STEP_SEND_INPUT_EVENT_UI",1383124094081418,1383124094617418,1383124094661418,6414,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6414,1383124094661418,320000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383124094988418,1383124094617418,1383124094887418,6414,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6414,1383124094887418,10000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383124094988418,1383124119033418,1383124119033418,6414,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6414,1383124119033418,8738000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383124127771418,1383124119033418,1383124127596418,6414,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6414,1383124127596418,7000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383124127771418,1383124127712418,1383124127712418,6414,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6414,1383124127712418,19000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383124127731418,1383124207955418,1383124207955418,6414,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6414,1383124207955418,19000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383124207974418,1383124213046418,1383124213046418,6414,"STEP_SWAP_BUFFERS"
+6414,1383124213046418,22000,0,"STEP_SWAP_BUFFERS",1383124213068418,1383124221194418,1383124221194418,6414,"STEP_DRAW_AND_SWAP"
+6414,1383124221194418,20000,0,"STEP_DRAW_AND_SWAP",1383124221214418,1383124261843418,1383124261843418,6414,"STEP_FINISHED_SWAP_BUFFERS"
+6414,1383124261843418,37000,0,"STEP_FINISHED_SWAP_BUFFERS",1383124261880418,"[NULL]",1383125521558418,6552,"AsyncBegin"
+6552,1383125521558418,161901000,0,"AsyncBegin",1383125521558418,1383125525770418,1383125525814418,6552,"Begin"
+6552,1383125525814418,6000,0,"Begin",1383125526039418,1383125525770418,1383125525888418,6552,"STEP_SEND_INPUT_EVENT_UI"
+6552,1383125525888418,141000,0,"STEP_SEND_INPUT_EVENT_UI",1383125526039418,1383125529143418,1383125529178418,6552,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6552,1383125529178418,162000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383125529344418,1383125529143418,1383125529282418,6552,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6552,1383125529282418,5000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383125529344418,1383125581612418,1383125581612418,6552,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6552,1383125581612418,12061000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383125593673418,1383125581612418,1383125593621418,6552,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6552,1383125593621418,7000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383125593673418,1383125593686418,1383125593686418,6552,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6552,1383125593686418,11000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383125593697418,1383125647723418,1383125647723418,6552,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6552,1383125647723418,23000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383125647746418,1383125654069418,1383125654069418,6552,"STEP_SWAP_BUFFERS"
+6552,1383125654069418,19000,0,"STEP_SWAP_BUFFERS",1383125654088418,1383125663282418,1383125663282418,6552,"STEP_DRAW_AND_SWAP"
+6552,1383125663282418,20000,0,"STEP_DRAW_AND_SWAP",1383125663302418,1383125683484418,1383125683484418,6552,"STEP_FINISHED_SWAP_BUFFERS"
+6552,1383125683484418,19000,0,"STEP_FINISHED_SWAP_BUFFERS",1383125683503418,"[NULL]",1383126581558418,6602,"AsyncBegin"
+6602,1383126581558418,87964000,0,"AsyncBegin",1383126581558418,1383126586079418,1383126586122418,6602,"Begin"
+6602,1383126586122418,6000,0,"Begin",1383126586328418,1383126586079418,1383126586193418,6602,"STEP_SEND_INPUT_EVENT_UI"
+6602,1383126586193418,126000,0,"STEP_SEND_INPUT_EVENT_UI",1383126586328418,1383126588328418,1383126588364418,6602,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6602,1383126588364418,821000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383126589192418,1383126588328418,1383126589084418,6602,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6602,1383126589084418,11000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383126589192418,1383126595233418,1383126595233418,6602,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6602,1383126595233418,8145000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383126603378418,1383126595233418,1383126603302418,6602,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6602,1383126603302418,7000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383126603378418,1383126603940418,1383126603940418,6602,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6602,1383126603940418,5000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383126603945418,1383126630232418,1383126630232418,6602,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6602,1383126630232418,17000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383126630249418,1383126634508418,1383126634508418,6602,"STEP_SWAP_BUFFERS"
+6602,1383126634508418,9000,0,"STEP_SWAP_BUFFERS",1383126634517418,1383126642230418,1383126642230418,6602,"STEP_DRAW_AND_SWAP"
+6602,1383126642230418,20000,0,"STEP_DRAW_AND_SWAP",1383126642250418,1383126669549418,1383126669549418,6602,"STEP_FINISHED_SWAP_BUFFERS"
+6602,1383126669549418,14000,0,"STEP_FINISHED_SWAP_BUFFERS",1383126669563418,"[NULL]",1383127076558418,6693,"AsyncBegin"
+6693,1383127076558418,140115000,1,"AsyncBegin",1383127076558418,1383127082044418,1383127082090418,6693,"Begin"
+6693,1383127082090418,7000,1,"Begin",1383127082341418,1383127082044418,1383127082166418,6693,"STEP_SEND_INPUT_EVENT_UI"
+6693,1383127082166418,164000,1,"STEP_SEND_INPUT_EVENT_UI",1383127082341418,1383127082917418,1383127082960418,6693,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6693,1383127082960418,348000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383127083315418,1383127082917418,1383127083114418,6693,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6693,1383127083114418,9000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383127083315418,1383127096393418,1383127096393418,6693,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6693,1383127096393418,7736000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383127104129418,1383127096393418,1383127104038418,6693,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6693,1383127104038418,7000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383127104129418,1383127104330418,1383127104330418,6693,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6693,1383127104330418,12000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383127104342418,1383127168839418,1383127168839418,6693,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6693,1383127168839418,36000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383127168875418,1383127175184418,1383127175184418,6693,"STEP_SWAP_BUFFERS"
+6693,1383127175184418,22000,1,"STEP_SWAP_BUFFERS",1383127175206418,1383127201828418,1383127201828418,6693,"STEP_DRAW_AND_SWAP"
+6693,1383127201828418,31000,1,"STEP_DRAW_AND_SWAP",1383127201859418,1383127216685418,1383127216685418,6693,"STEP_FINISHED_SWAP_BUFFERS"
+6693,1383127216685418,18000,1,"STEP_FINISHED_SWAP_BUFFERS",1383127216703418,"[NULL]",1383127670558418,6698,"AsyncBegin"
+6698,1383127670558418,301236000,1,"AsyncBegin",1383127670558418,1383127698512418,1383127698547418,6698,"Begin"
+6698,1383127698547418,6000,1,"Begin",1383127698732418,1383127698512418,1383127698610418,6698,"STEP_SEND_INPUT_EVENT_UI"
+6698,1383127698610418,113000,1,"STEP_SEND_INPUT_EVENT_UI",1383127698732418,1383127699155418,1383127699173418,6698,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6698,1383127699173418,196000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383127699373418,1383127699155418,1383127699323418,6698,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6698,1383127699323418,4000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383127699373418,1383127844723418,1383127844723418,6698,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6698,1383127844723418,14082000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383127858805418,1383127844723418,1383127858076418,6698,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6698,1383127858076418,7000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383127858805418,1383127861637418,1383127861637418,6698,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6698,1383127861637418,13000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383127861650418,1383127928519418,1383127928519418,6698,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6698,1383127928519418,3000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383127928522418,1383127936811418,1383127936811418,6698,"STEP_SWAP_BUFFERS"
+6698,1383127936811418,8000,1,"STEP_SWAP_BUFFERS",1383127936819418,1383127949728418,1383127949728418,6698,"STEP_DRAW_AND_SWAP"
+6698,1383127949728418,7000,1,"STEP_DRAW_AND_SWAP",1383127949735418,1383127971881418,1383127971881418,6698,"STEP_FINISHED_SWAP_BUFFERS"
+6698,1383127971881418,7000,1,"STEP_FINISHED_SWAP_BUFFERS",1383127971888418,"[NULL]",1383127837558418,6723,"AsyncBegin"
+6723,1383127837558418,134236000,0,"AsyncBegin",1383127837558418,1383127846715418,1383127846793418,6723,"Begin"
+6723,1383127846793418,11000,0,"Begin",1383127847217418,1383127846715418,1383127846940418,6723,"STEP_SEND_INPUT_EVENT_UI"
+6723,1383127846940418,255000,0,"STEP_SEND_INPUT_EVENT_UI",1383127847217418,1383127848602418,1383127848665418,6723,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6723,1383127848665418,1045000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383127849717418,1383127848602418,1383127849609418,6723,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6723,1383127849609418,12000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383127849717418,1383127874642418,1383127874642418,6723,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6723,1383127874642418,8527000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383127883169418,1383127874642418,1383127883061418,6723,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6723,1383127883061418,8000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383127883169418,1383127885270418,1383127885270418,6723,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6723,1383127885270418,14000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383127885284418,1383127928530418,1383127928530418,6723,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6723,1383127928530418,3000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383127928533418,1383127936838418,1383127936838418,6723,"STEP_SWAP_BUFFERS"
+6723,1383127936838418,8000,0,"STEP_SWAP_BUFFERS",1383127936846418,1383127949753418,1383127949753418,6723,"STEP_DRAW_AND_SWAP"
+6723,1383127949753418,7000,0,"STEP_DRAW_AND_SWAP",1383127949760418,1383127971906418,1383127971906418,6723,"STEP_FINISHED_SWAP_BUFFERS"
+6723,1383127971906418,7000,0,"STEP_FINISHED_SWAP_BUFFERS",1383127971913418,"[NULL]",1383129053558418,6802,"AsyncBegin"
+6802,1383129053558418,163272000,0,"AsyncBegin",1383129053558418,1383129081907418,1383129081950418,6802,"Begin"
+6802,1383129081950418,46000,0,"Begin",1383129082214418,1383129081907418,1383129082066418,6802,"STEP_SEND_INPUT_EVENT_UI"
+6802,1383129082066418,138000,0,"STEP_SEND_INPUT_EVENT_UI",1383129082214418,1383129082616418,1383129082657418,6802,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6802,1383129082657418,782000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383129083446418,1383129082616418,1383129083335418,6802,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6802,1383129083335418,10000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383129083446418,1383129105125418,1383129105125418,6802,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6802,1383129105125418,6978000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383129112103418,1383129105125418,1383129111999418,6802,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6802,1383129111999418,8000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383129112103418,1383129113877418,1383129113877418,6802,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6802,1383129113877418,12000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383129113889418,1383129155519418,1383129155519418,6802,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6802,1383129155519418,18000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383129155537418,1383129177753418,1383129177753418,6802,"STEP_SWAP_BUFFERS"
+6802,1383129177753418,30000,0,"STEP_SWAP_BUFFERS",1383129177783418,1383129181587418,1383129181587418,6802,"STEP_DRAW_AND_SWAP"
+6802,1383129181587418,21000,0,"STEP_DRAW_AND_SWAP",1383129181608418,1383129216866418,1383129216866418,6802,"STEP_FINISHED_SWAP_BUFFERS"
+6802,1383129216866418,29000,0,"STEP_FINISHED_SWAP_BUFFERS",1383129216895418,"[NULL]",1383129492558418,6877,"AsyncBegin"
+6877,1383129492558418,370407000,1,"AsyncBegin",1383129492558418,1383129497787418,1383129497859418,6877,"Begin"
+6877,1383129497859418,11000,1,"Begin",1383129498184418,1383129497787418,1383129497995418,6877,"STEP_SEND_INPUT_EVENT_UI"
+6877,1383129497995418,168000,1,"STEP_SEND_INPUT_EVENT_UI",1383129498184418,1383129498483418,1383129498503418,6877,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6877,1383129498503418,329000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383129498836418,1383129498483418,1383129498775418,6877,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6877,1383129498775418,5000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383129498836418,1383129719266418,1383129719266418,6877,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6877,1383129719266418,24639000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383129743905418,1383129719266418,1383129742223418,6877,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6877,1383129742223418,13000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383129743905418,1383129743178418,1383129743178418,6877,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6877,1383129743178418,12000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383129743190418,1383129816012418,1383129816012418,6877,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6877,1383129816012418,18000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383129816030418,1383129823726418,1383129823726418,6877,"STEP_SWAP_BUFFERS"
+6877,1383129823726418,46000,1,"STEP_SWAP_BUFFERS",1383129823772418,1383129835535418,1383129835535418,6877,"STEP_DRAW_AND_SWAP"
+6877,1383129835535418,18000,1,"STEP_DRAW_AND_SWAP",1383129835553418,1383129863003418,1383129863003418,6877,"STEP_FINISHED_SWAP_BUFFERS"
+6877,1383129863003418,30000,1,"STEP_FINISHED_SWAP_BUFFERS",1383129863033418,"[NULL]",1383130519558418,6911,"AsyncBegin"
+6911,1383130519558418,198057000,1,"AsyncBegin",1383130519558418,1383130544003418,1383130544042418,6911,"Begin"
+6911,1383130544042418,7000,1,"Begin",1383130544237418,1383130544003418,1383130544113418,6911,"STEP_SEND_INPUT_EVENT_UI"
+6911,1383130544113418,115000,1,"STEP_SEND_INPUT_EVENT_UI",1383130544237418,1383130546898418,1383130546932418,6911,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6911,1383130546932418,833000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383130547772418,1383130546898418,1383130547581418,6911,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6911,1383130547581418,10000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130547772418,1383130555182418,1383130555182418,6911,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6911,1383130555182418,18263000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383130573445418,1383130555182418,1383130573221418,6911,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6911,1383130573221418,12000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130573445418,1383130573311418,1383130573311418,6911,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6911,1383130573311418,10000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383130573321418,1383130656314418,1383130656314418,6911,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6911,1383130656314418,11000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130656325418,1383130667367418,1383130667367418,6911,"STEP_SWAP_BUFFERS"
+6911,1383130667367418,17000,1,"STEP_SWAP_BUFFERS",1383130667384418,1383130681350418,1383130681350418,6911,"STEP_DRAW_AND_SWAP"
+6911,1383130681350418,25000,1,"STEP_DRAW_AND_SWAP",1383130681375418,1383130717639418,1383130717639418,6911,"STEP_FINISHED_SWAP_BUFFERS"
+6911,1383130717639418,18000,1,"STEP_FINISHED_SWAP_BUFFERS",1383130717657418,"[NULL]",1383130553558418,6915,"AsyncBegin"
+6915,1383130553558418,164057000,0,"AsyncBegin",1383130553558418,1383130558151418,1383130558197418,6915,"Begin"
+6915,1383130558197418,6000,0,"Begin",1383130558425418,1383130558151418,1383130558273418,6915,"STEP_SEND_INPUT_EVENT_UI"
+6915,1383130558273418,141000,0,"STEP_SEND_INPUT_EVENT_UI",1383130558425418,1383130558645418,1383130558675418,6915,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6915,1383130558675418,155000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383130558834418,1383130558645418,1383130558779418,6915,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6915,1383130558779418,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130558834418,1383130587655418,1383130587655418,6915,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6915,1383130587655418,7138000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383130594793418,1383130587655418,1383130594603418,6915,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6915,1383130594603418,6000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130594793418,1383130594791418,1383130594791418,6915,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6915,1383130594791418,20000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383130594811418,1383130656335418,1383130656335418,6915,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6915,1383130656335418,4000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130656339418,1383130667392418,1383130667392418,6915,"STEP_SWAP_BUFFERS"
+6915,1383130667392418,3000,0,"STEP_SWAP_BUFFERS",1383130667395418,1383130681397418,1383130681397418,6915,"STEP_DRAW_AND_SWAP"
+6915,1383130681397418,7000,0,"STEP_DRAW_AND_SWAP",1383130681404418,1383130717665418,1383130717665418,6915,"STEP_FINISHED_SWAP_BUFFERS"
+6915,1383130717665418,3000,0,"STEP_FINISHED_SWAP_BUFFERS",1383130717668418,"[NULL]",1383130681558418,6940,"AsyncBegin"
+6940,1383130681558418,167758000,0,"AsyncBegin",1383130681558418,1383130686495418,1383130686567418,6940,"Begin"
+6940,1383130686567418,13000,0,"Begin",1383130686909418,1383130686495418,1383130686705418,6940,"STEP_SEND_INPUT_EVENT_UI"
+6940,1383130686705418,184000,0,"STEP_SEND_INPUT_EVENT_UI",1383130686909418,1383130687055418,1383130687081418,6940,"STEP_HANDLE_INPUT_EVENT_IMPL"
+6940,1383130687081418,334000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383130687419418,1383130687055418,1383130687360418,6940,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
+6940,1383130687360418,5000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130687419418,1383130719656418,1383130719656418,6940,"STEP_HANDLE_INPUT_EVENT_MAIN"
+6940,1383130719656418,8298000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383130727954418,1383130719656418,1383130727856418,6940,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
+6940,1383130727856418,7000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130727954418,1383130728343418,1383130728343418,6940,"STEP_HANDLED_INPUT_EVENT_IMPL"
+6940,1383130728343418,13000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383130728356418,1383130815135418,1383130815135418,6940,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
+6940,1383130815135418,19000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130815154418,1383130825051418,1383130825051418,6940,"STEP_SWAP_BUFFERS"
+6940,1383130825051418,35000,0,"STEP_SWAP_BUFFERS",1383130825086418,1383130834387418,1383130834387418,6940,"STEP_DRAW_AND_SWAP"
+6940,1383130834387418,18000,0,"STEP_DRAW_AND_SWAP",1383130834405418,1383130849338418,1383130849338418,6940,"STEP_FINISHED_SWAP_BUFFERS"
+6940,1383130849338418,17000,0,"STEP_FINISHED_SWAP_BUFFERS",1383130849355418,"[NULL]","[NULL]","[NULL]","[NULL]"
diff --git a/test/trace_processor/chrome/touch_flow_event.sql b/test/trace_processor/chrome/touch_flow_event.sql
new file mode 100644
index 0000000..dbb5c89
--- /dev/null
+++ b/test/trace_processor/chrome/touch_flow_event.sql
@@ -0,0 +1,29 @@
+--
+-- 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/touch_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 touch_flow_event
+ORDER BY touch_id, trace_id, ts;
diff --git a/test/trace_processor/chrome/touch_flow_event_queuing_delay.out b/test/trace_processor/chrome/touch_flow_event_queuing_delay.out
new file mode 100644
index 0000000..aa26ef6
--- /dev/null
+++ b/test/trace_processor/chrome/touch_flow_event_queuing_delay.out
@@ -0,0 +1,38 @@
+
+"trace_id","jank","step","next_step","ancestor_end","maybe_next_ancestor_ts","queuing_time_ns"
+6911,1,"AsyncBegin","Begin",1383130519558418,1383130544003418,24445000
+6911,1,"Begin","STEP_SEND_INPUT_EVENT_UI",1383130544237418,1383130544003418,0
+6911,1,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",1383130544237418,1383130546898418,2661000
+6911,1,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130547772418,1383130546898418,0
+6911,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_HANDLE_INPUT_EVENT_MAIN",1383130547772418,1383130555182418,7410000
+6911,1,"STEP_HANDLE_INPUT_EVENT_MAIN","STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130573445418,1383130555182418,0
+6911,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL","STEP_HANDLED_INPUT_EVENT_IMPL",1383130573445418,1383130573311418,0
+6911,1,"STEP_HANDLED_INPUT_EVENT_IMPL","STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130573321418,1383130656314418,82993000
+6911,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT","STEP_SWAP_BUFFERS",1383130656325418,1383130667367418,11042000
+6911,1,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",1383130667384418,1383130681350418,13966000
+6911,1,"STEP_DRAW_AND_SWAP","STEP_FINISHED_SWAP_BUFFERS",1383130681375418,1383130717639418,36264000
+6911,1,"STEP_FINISHED_SWAP_BUFFERS","AsyncBegin",1383130717657418,"[NULL]","[NULL]"
+6915,0,"AsyncBegin","Begin",1383130553558418,1383130558151418,4593000
+6915,0,"Begin","STEP_SEND_INPUT_EVENT_UI",1383130558425418,1383130558151418,0
+6915,0,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",1383130558425418,1383130558645418,220000
+6915,0,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130558834418,1383130558645418,0
+6915,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_HANDLE_INPUT_EVENT_MAIN",1383130558834418,1383130587655418,28821000
+6915,0,"STEP_HANDLE_INPUT_EVENT_MAIN","STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130594793418,1383130587655418,0
+6915,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL","STEP_HANDLED_INPUT_EVENT_IMPL",1383130594793418,1383130594791418,0
+6915,0,"STEP_HANDLED_INPUT_EVENT_IMPL","STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130594811418,1383130656335418,61524000
+6915,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT","STEP_SWAP_BUFFERS",1383130656339418,1383130667392418,11053000
+6915,0,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",1383130667395418,1383130681397418,14002000
+6915,0,"STEP_DRAW_AND_SWAP","STEP_FINISHED_SWAP_BUFFERS",1383130681404418,1383130717665418,36261000
+6915,0,"STEP_FINISHED_SWAP_BUFFERS","AsyncBegin",1383130717668418,"[NULL]","[NULL]"
+6940,0,"AsyncBegin","Begin",1383130681558418,1383130686495418,4937000
+6940,0,"Begin","STEP_SEND_INPUT_EVENT_UI",1383130686909418,1383130686495418,0
+6940,0,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",1383130686909418,1383130687055418,146000
+6940,0,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130687419418,1383130687055418,0
+6940,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_HANDLE_INPUT_EVENT_MAIN",1383130687419418,1383130719656418,32237000
+6940,0,"STEP_HANDLE_INPUT_EVENT_MAIN","STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130727954418,1383130719656418,0
+6940,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL","STEP_HANDLED_INPUT_EVENT_IMPL",1383130727954418,1383130728343418,389000
+6940,0,"STEP_HANDLED_INPUT_EVENT_IMPL","STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130728356418,1383130815135418,86779000
+6940,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT","STEP_SWAP_BUFFERS",1383130815154418,1383130825051418,9897000
+6940,0,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",1383130825086418,1383130834387418,9301000
+6940,0,"STEP_DRAW_AND_SWAP","STEP_FINISHED_SWAP_BUFFERS",1383130834405418,1383130849338418,14933000
+6940,0,"STEP_FINISHED_SWAP_BUFFERS","[NULL]",1383130849355418,"[NULL]","[NULL]"
diff --git a/test/trace_processor/chrome/touch_flow_event_queuing_delay.sql b/test/trace_processor/chrome/touch_flow_event_queuing_delay.sql
new file mode 100644
index 0000000..0230908
--- /dev/null
+++ b/test/trace_processor/chrome/touch_flow_event_queuing_delay.sql
@@ -0,0 +1,30 @@
+--
+-- 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/touch_flow_event_queuing_delay.sql')
+ AS suppress_query_output;
+
+-- trace 6911 is janky and 6915 and 6940 succeed it (both are not janky).
+SELECT
+ trace_id,
+ jank,
+ step,
+ next_step,
+ ancestor_end,
+ maybe_next_ancestor_ts,
+ queuing_time_ns
+FROM touch_flow_event_queuing_delay
+WHERE trace_id = 6915 OR trace_id = 6911 OR trace_id = 6940
+ORDER BY trace_id, ts;
diff --git a/test/trace_processor/chrome/touch_flow_event_queuing_delay_full.sql b/test/trace_processor/chrome/touch_flow_event_queuing_delay_full.sql
new file mode 100644
index 0000000..f1e9c33
--- /dev/null
+++ b/test/trace_processor/chrome/touch_flow_event_queuing_delay_full.sql
@@ -0,0 +1,29 @@
+--
+-- 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/touch_flow_event_queuing_delay.sql')
+ AS suppress_query_output;
+
+-- trace 6911 is janky and 6915 and 6940 succeed it (both are not janky).
+SELECT
+ trace_id,
+ jank,
+ step,
+ next_step,
+ ancestor_end,
+ maybe_next_ancestor_ts,
+ queuing_time_ns
+FROM touch_flow_event_queuing_delay
+ORDER BY trace_id, ts;
diff --git a/test/trace_processor/chrome/touch_flow_event_queuing_delay_synth.out b/test/trace_processor/chrome/touch_flow_event_queuing_delay_synth.out
new file mode 100644
index 0000000..7c5c8b0
--- /dev/null
+++ b/test/trace_processor/chrome/touch_flow_event_queuing_delay_synth.out
@@ -0,0 +1,12 @@
+
+"trace_id","jank","step","next_step","ancestor_end","maybe_next_ancestor_ts","queuing_time_ns"
+34577,0,"AsyncBegin","Begin",0,0,0
+34577,0,"Begin","End",1000000,11000000,10000000
+34577,0,"End","AsyncBegin",12000000,"[NULL]","[NULL]"
+34578,1,"AsyncBegin","Begin",16000000,16000000,0
+34578,1,"Begin","End",17000000,50000000,33000000
+34578,1,"End","AsyncBegin",51000000,"[NULL]","[NULL]"
+34579,0,"AsyncBegin","Begin",55000000,55000000,0
+34579,0,"Begin","STEP_SEND_INPUT_EVENT_UI",56000000,87000000,31000000
+34579,0,"STEP_SEND_INPUT_EVENT_UI","End",88000000,89000000,1000000
+34579,0,"End","[NULL]",90000000,"[NULL]","[NULL]"
diff --git a/test/trace_processor/chrome/touch_flow_event_synth.out b/test/trace_processor/chrome/touch_flow_event_synth.out
new file mode 100644
index 0000000..570f3c0
--- /dev/null
+++ b/test/trace_processor/chrome/touch_flow_event_synth.out
@@ -0,0 +1,12 @@
+
+"trace_id","ts","dur","jank","step","ancestor_end","maybe_next_ancestor_ts","next_ts","next_trace_id","next_step"
+34577,0,10000000,0,"AsyncBegin",0,0,0,34577,"Begin"
+34577,0,1000000,0,"Begin",1000000,11000000,11000000,34577,"End"
+34577,11000000,1000000,0,"End",12000000,"[NULL]",16000000,34578,"AsyncBegin"
+34578,16000000,33000000,1,"AsyncBegin",16000000,16000000,16000000,34578,"Begin"
+34578,16000000,1000000,1,"Begin",17000000,50000000,50000000,34578,"End"
+34578,50000000,1000000,1,"End",51000000,"[NULL]",55000000,34579,"AsyncBegin"
+34579,55000000,33000000,0,"AsyncBegin",55000000,55000000,55000000,34579,"Begin"
+34579,55000000,1000000,0,"Begin",56000000,87000000,87000000,34579,"STEP_SEND_INPUT_EVENT_UI"
+34579,87000000,1000000,0,"STEP_SEND_INPUT_EVENT_UI",88000000,89000000,89000000,34579,"End"
+34579,89000000,1000000,0,"End",90000000,"[NULL]","[NULL]","[NULL]","[NULL]"
diff --git a/test/trace_processor/chrome/touch_jank.out b/test/trace_processor/chrome/touch_jank.out
new file mode 100644
index 0000000..9f55ea8
--- /dev/null
+++ b/test/trace_processor/chrome/touch_jank.out
@@ -0,0 +1,16 @@
+
+"touch_id","trace_id","jank","ts","dur"
+6280,6288,1,1383122421558418,226350000
+6280,6312,0,1383122543558418,185244000
+6318,6328,1,1383123604558418,207945000
+6318,6414,0,1383124088558418,173233000
+6420,6552,0,1383125521558418,161901000
+6586,6602,0,1383126581558418,87964000
+6586,6693,1,1383127076558418,140115000
+6697,6698,1,1383127670558418,301236000
+6697,6723,0,1383127837558418,134236000
+6788,6802,0,1383129053558418,163272000
+6788,6877,1,1383129492558418,370407000
+6906,6911,1,1383130519558418,198057000
+6906,6915,0,1383130553558418,164057000
+6906,6940,0,1383130681558418,167758000
diff --git a/test/trace_processor/chrome/touch_jank.py b/test/trace_processor/chrome/touch_jank.py
new file mode 100644
index 0000000..0dd0e8d
--- /dev/null
+++ b/test/trace_processor/chrome/touch_jank.py
@@ -0,0 +1,186 @@
+#!/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
+
+touch_move_trace_id = 34576
+trace_id1 = touch_move_trace_id + 1
+trace_id2 = trace_id1 + 1
+trace_id3 = trace_id2 + 1
+touch_end_trace_id = trace_id3 + 1
+
+touch_gesture_id = 87654
+
+flow_id1 = 45678
+flow_id2 = 45679
+flow_id3 = 45680
+
+trace.add_input_latency_event_slice(
+ "TouchStart",
+ ts=ms_to_ns(0),
+ dur=ms_to_ns(1),
+ track=touch_move_trace_id,
+ trace_id=touch_move_trace_id,
+ touch_id=touch_gesture_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)
+
+# Touch move 1 - not janky
+trace.add_input_latency_event_slice(
+ "TouchMove",
+ ts=ms_to_ns(0),
+ dur=ms_to_ns(10),
+ track=trace_id1,
+ trace_id=trace_id1,
+ touch_id=touch_gesture_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" touch move 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" touch move 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])
+
+# Touch move 2 - janky
+trace.add_input_latency_event_slice(
+ "TouchMove",
+ ts=ms_to_ns(16),
+ dur=ms_to_ns(33),
+ track=trace_id2,
+ trace_id=trace_id2,
+ touch_id=touch_gesture_id,
+ is_coalesced=0)
+
+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" touch move 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" touch move 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])
+
+# Touch move 3 - janky
+trace.add_input_latency_event_slice(
+ "TouchMove",
+ ts=ms_to_ns(55),
+ dur=ms_to_ns(33),
+ track=trace_id3,
+ trace_id=trace_id3,
+ touch_id=touch_gesture_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" touch move 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)
+# This ends the blocking slices of "janky" touch move 3.
+
+trace.add_latency_info_flow(
+ ts=ms_to_ns(87),
+ dur=ms_to_ns(1),
+ trusted_sequence_id=seq1,
+ trace_id=trace_id3,
+ step=trace.prototypes.ChromeLatencyInfo.Step.STEP_SEND_INPUT_EVENT_UI,
+ terminating_flow_ids=[flow_id3])
+
+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(
+ "TouchEnd",
+ ts=ms_to_ns(90),
+ dur=ms_to_ns(2),
+ track=touch_end_trace_id,
+ trace_id=touch_end_trace_id,
+ touch_id=touch_gesture_id)
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/touch_jank.sql b/test/trace_processor/chrome/touch_jank.sql
new file mode 100644
index 0000000..723b146
--- /dev/null
+++ b/test/trace_processor/chrome/touch_jank.sql
@@ -0,0 +1,24 @@
+--
+-- 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/touch_jank.sql') AS suppress_query_output;
+
+SELECT
+ touch_id,
+ trace_id,
+ jank,
+ ts,
+ dur
+FROM touch_jank;
diff --git a/test/trace_processor/chrome/touch_jank_synth.out b/test/trace_processor/chrome/touch_jank_synth.out
new file mode 100644
index 0000000..0c6f96f
--- /dev/null
+++ b/test/trace_processor/chrome/touch_jank_synth.out
@@ -0,0 +1,5 @@
+
+"touch_id","trace_id","jank","ts","dur"
+87654,34577,0,0,10000000
+87654,34578,1,16000000,33000000
+87654,34579,0,55000000,33000000
diff --git a/test/trace_processor/dynamic/ancestor_slice_by_stack.out b/test/trace_processor/dynamic/ancestor_slice_by_stack.out
new file mode 100644
index 0000000..13881bc
--- /dev/null
+++ b/test/trace_processor/dynamic/ancestor_slice_by_stack.out
@@ -0,0 +1,5 @@
+"ts","name"
+1000,"event_depth_0"
+2000,"event_depth_1"
+8000,"event_depth_0"
+9000,"event_depth_1"
diff --git a/test/trace_processor/dynamic/ancestor_slice_by_stack.sql b/test/trace_processor/dynamic/ancestor_slice_by_stack.sql
new file mode 100644
index 0000000..3b5089e
--- /dev/null
+++ b/test/trace_processor/dynamic/ancestor_slice_by_stack.sql
@@ -0,0 +1,5 @@
+SELECT ts, name FROM ancestor_slice_by_stack((
+ SELECT stack_id FROM slice
+ WHERE name = 'event_depth_2'
+ LIMIT 1
+));
diff --git a/test/trace_processor/dynamic/descendant_slice_by_stack.out b/test/trace_processor/dynamic/descendant_slice_by_stack.out
new file mode 100644
index 0000000..c32f639
--- /dev/null
+++ b/test/trace_processor/dynamic/descendant_slice_by_stack.out
@@ -0,0 +1,5 @@
+"ts","name"
+2000,"event_depth_1"
+3000,"event_depth_2"
+9000,"event_depth_1"
+10000,"event_depth_2"
diff --git a/test/trace_processor/dynamic/descendant_slice_by_stack.sql b/test/trace_processor/dynamic/descendant_slice_by_stack.sql
new file mode 100644
index 0000000..ac42bda
--- /dev/null
+++ b/test/trace_processor/dynamic/descendant_slice_by_stack.sql
@@ -0,0 +1,6 @@
+SELECT ts, name FROM descendant_slice_by_stack((
+ SELECT stack_id FROM slice
+ WHERE name = 'event_depth_0'
+ LIMIT 1
+));
+
diff --git a/test/trace_processor/dynamic/index b/test/trace_processor/dynamic/index
index 3c5953b..6fe5cf1 100644
--- a/test/trace_processor/dynamic/index
+++ b/test/trace_processor/dynamic/index
@@ -6,6 +6,12 @@
# Descendant slice table.
relationship_tables.textproto descendant_slice.sql descendant_slice.out
+# Ancestor slice by stack table.
+slice_stacks.textproto ancestor_slice_by_stack.sql ancestor_slice_by_stack.out
+
+# Descendant slice by stack table.
+slice_stacks.textproto descendant_slice_by_stack.sql descendant_slice_by_stack.out
+
# Connected/Following/Perceeding flow table.
connected_flow_data.json connected_flow.sql connected_flow.out
diff --git a/test/trace_processor/dynamic/slice_stacks.textproto b/test/trace_processor/dynamic/slice_stacks.textproto
new file mode 100644
index 0000000..8361afc
--- /dev/null
+++ b/test/trace_processor/dynamic/slice_stacks.textproto
@@ -0,0 +1,154 @@
+# 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
+ }
+ }
+}
+
+# Thread track is nested underneath this process track.
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ track_descriptor {
+ uuid: 10
+ process {
+ pid: 5
+ process_name: "p1"
+ }
+ }
+}
+
+# ----------------------
+# Slices
+# ----------------------
+
+# We create stacks of various depths on track "t1".
+# t1 |-------------| |-------------|
+# |-------| |-------|
+# |-| |-|
+
+# Should appear on default track "t1", range from 1000 to 6000.
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 1000
+ track_event {
+ categories: "cat"
+ name: "event_depth_0"
+ type: 1
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 2000
+ track_event {
+ categories: "cat"
+ name: "event_depth_1"
+ type: 1
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 3000
+ track_event {
+ categories: "cat"
+ name: "event_depth_2"
+ type: 1
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 4000
+ track_event {
+ categories: "cat"
+ name: "event_depth_2"
+ type: 2
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 5000
+ track_event {
+ categories: "cat"
+ name: "event_depth_1"
+ type: 2
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 6000
+ track_event {
+ categories: "cat"
+ name: "event_depth_0"
+ type: 2
+ }
+}
+
+# Should appear on default track "t1", range from 8000 to 13000.
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 8000
+ track_event {
+ categories: "cat"
+ name: "event_depth_0"
+ type: 1
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 9000
+ track_event {
+ categories: "cat"
+ name: "event_depth_1"
+ type: 1
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 10000
+ track_event {
+ categories: "cat"
+ name: "event_depth_2"
+ type: 1
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 11000
+ track_event {
+ categories: "cat"
+ name: "event_depth_2"
+ type: 2
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 12000
+ track_event {
+ categories: "cat"
+ name: "event_depth_1"
+ type: 2
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 13000
+ track_event {
+ categories: "cat"
+ name: "event_depth_0"
+ type: 2
+ }
+}
diff --git a/test/trace_processor/graphics/android_sysui_cuj.out b/test/trace_processor/graphics/android_sysui_cuj.out
index fffda29..9d81d7b 100644
--- a/test/trace_processor/graphics/android_sysui_cuj.out
+++ b/test/trace_processor/graphics/android_sysui_cuj.out
@@ -1,7 +1,7 @@
android_sysui_cuj {
cuj_name: "SHADE_ROW_EXPAND"
cuj_start: 10
- cuj_dur: 1000000000
+ cuj_dur: 401000000
process {
name: "com.android.systemui"
uid: 10001
diff --git a/test/trace_processor/graphics/android_sysui_cuj.py b/test/trace_processor/graphics/android_sysui_cuj.py
index 14dc2b0..a3a8254 100644
--- a/test/trace_processor/graphics/android_sysui_cuj.py
+++ b/test/trace_processor/graphics/android_sysui_cuj.py
@@ -117,7 +117,7 @@
trace.add_ftrace_packet(cpu=0)
trace.add_atrace_async_begin(ts=10, tid=PID, pid=PID, buf="J<SHADE_ROW_EXPAND>")
trace.add_atrace_async_end(
- ts=1_000_000_010, tid=PID, pid=PID, buf="J<SHADE_ROW_EXPAND>")
+ ts=401_000_010, tid=PID, pid=PID, buf="J<SHADE_ROW_EXPAND>")
add_frame(
trace,
@@ -137,14 +137,14 @@
add_frame(
trace,
vsync=20,
- ts_do_frame=8_000_000,
+ ts_do_frame=20_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")
+ trace, ts=9_000_000, ts_end=19_000_000, buf="binder transaction")
add_render_thread_atrace(
trace, ts=24_000_000, ts_end=25_000_000, buf="flush layers")
diff --git a/test/trace_processor/graphics/dpu_vote_clock_bw.out b/test/trace_processor/graphics/dpu_vote_clock_bw.out
new file mode 100644
index 0000000..78ad37b
--- /dev/null
+++ b/test/trace_processor/graphics/dpu_vote_clock_bw.out
@@ -0,0 +1,17 @@
+android_hwcomposer {
+ skipped_validation_count: 0
+ unskipped_validation_count: 0
+ separated_validation_count: 0
+ unknown_validation_count: 0
+ dpu_vote_metrics {
+ tid: 237
+ avg_dpu_vote_clock: 206250
+ avg_dpu_vote_avg_bw: 210000
+ avg_dpu_vote_peak_bw: 205000
+ avg_dpu_vote_rt_bw: 271000
+ }
+ dpu_vote_metrics {
+ tid: 299
+ avg_dpu_vote_clock: 250000
+ }
+}
diff --git a/test/trace_processor/graphics/dpu_vote_clock_bw.textproto b/test/trace_processor/graphics/dpu_vote_clock_bw.textproto
new file mode 100644
index 0000000..7da1d07
--- /dev/null
+++ b/test/trace_processor/graphics/dpu_vote_clock_bw.textproto
@@ -0,0 +1,127 @@
+packet {
+ ftrace_events {
+ cpu: 2
+ event {
+ timestamp: 1000000
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_clock"
+ type: 67
+ value: 200000
+ }
+ }
+ event {
+ timestamp: 2000000
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_avg_bw"
+ type: 67
+ value: 210000
+ }
+ }
+ event {
+ timestamp: 3000000
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_peak_bw"
+ type: 67
+ value: 210000
+ }
+ }
+ event {
+ timestamp: 4000000
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_clock"
+ type: 67
+ value: 210000
+ }
+ }
+ event {
+ timestamp: 5000000
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_avg_bw"
+ type: 67
+ value: 210000
+ }
+ }
+ event {
+ timestamp: 6000000
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_peak_bw"
+ type: 67
+ value: 200000
+ }
+ }
+ event {
+ timestamp: 7000000
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_clock"
+ type: 67
+ value: 210000
+ }
+ }
+ event {
+ timestamp: 7000000
+ pid: 299
+ dpu_tracing_mark_write {
+ pid: 299
+ name: "dpu_vote_clock"
+ type: 67
+ value: 200000
+ }
+ }
+ event {
+ timestamp: 8000000
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_avg_bw"
+ type: 67
+ value: 210000
+ }
+ }
+ event {
+ timestamp: 8000000
+ pid: 299
+ dpu_tracing_mark_write {
+ pid: 299
+ name: "dpu_vote_clock"
+ type: 67
+ value: 300000
+ }
+ }
+ event {
+ timestamp: 8000000
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_rt_bw"
+ type: 67
+ value: 271000
+ }
+ }
+ event {
+ timestamp: 8999999
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_peak_bw"
+ type: 67
+ value: 200000
+ }
+ }
+ }
+ trusted_uid: 9999
+ trusted_packet_sequence_id: 3
+}
\ No newline at end of file
diff --git a/test/trace_processor/graphics/frame_missed_metrics.out b/test/trace_processor/graphics/frame_missed_metrics.out
index ec59e69..aad41d2 100644
--- a/test/trace_processor/graphics/frame_missed_metrics.out
+++ b/test/trace_processor/graphics/frame_missed_metrics.out
@@ -3,4 +3,5 @@
missed_hwc_frames: 0
missed_gpu_frames: 0
missed_frame_rate: 0.42857142857142855 # = 3/7
+ gpu_invocations: 0
}
diff --git a/test/trace_processor/graphics/g2d_metrics.out b/test/trace_processor/graphics/g2d_metrics.out
index a28e4fd..86bd889 100644
--- a/test/trace_processor/graphics/g2d_metrics.out
+++ b/test/trace_processor/graphics/g2d_metrics.out
@@ -2,39 +2,39 @@
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_ms: 20
+ min_dur_ms: 20
+ avg_dur_ms: 20
}
- max_dur_ns: 20
- min_dur_ns: 20
- avg_dur_ns: 20
frame_count: 1
error_count: 0
+ max_dur_ms: 20
+ min_dur_ms: 20
+ avg_dur_ms: 20
}
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
+ max_dur_ms: 40
+ min_dur_ms: 20
+ avg_dur_ms: 30
}
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_ms: 40
+ min_dur_ms: 40
+ avg_dur_ms: 40
}
- max_dur_ns: 40
- min_dur_ns: 20
- avg_dur_ns: 33
frame_count: 3
error_count: 2
+ max_dur_ms: 40
+ min_dur_ms: 20
+ avg_dur_ms: 33.33333333333333
}
}
diff --git a/test/trace_processor/graphics/g2d_metrics.textproto b/test/trace_processor/graphics/g2d_metrics.textproto
index 9ed87bf..6a0eae9 100644
--- a/test/trace_processor/graphics/g2d_metrics.textproto
+++ b/test/trace_processor/graphics/g2d_metrics.textproto
@@ -2,7 +2,7 @@
ftrace_events {
cpu: 2
event {
- timestamp: 1000
+ timestamp: 1000000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -12,7 +12,7 @@
}
}
event {
- timestamp: 1003
+ timestamp: 1003000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -22,7 +22,7 @@
}
}
event {
- timestamp: 1005
+ timestamp: 1005000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -32,7 +32,7 @@
}
}
event {
- timestamp: 1010
+ timestamp: 1010000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -42,7 +42,7 @@
}
}
event {
- timestamp: 1020
+ timestamp: 1020000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -52,7 +52,7 @@
}
}
event {
- timestamp: 1030
+ timestamp: 1030000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -62,7 +62,7 @@
}
}
event {
- timestamp: 1040
+ timestamp: 1040000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -72,7 +72,7 @@
}
}
event {
- timestamp: 1050
+ timestamp: 1050000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -82,7 +82,7 @@
}
}
event {
- timestamp: 1060
+ timestamp: 1060000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -92,7 +92,7 @@
}
}
event {
- timestamp: 1070
+ timestamp: 1070000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -102,7 +102,7 @@
}
}
event {
- timestamp: 1080
+ timestamp: 1080000000
pid: 237
g2d_tracing_mark_write {
pid: 237
@@ -112,7 +112,7 @@
}
}
event {
- timestamp: 1085
+ timestamp: 1085000000
pid: 237
g2d_tracing_mark_write {
pid: 237
diff --git a/test/trace_processor/graphics/gpu_frequency_metric.out b/test/trace_processor/graphics/gpu_frequency_metric.out
new file mode 100644
index 0000000..dd9b0ab
--- /dev/null
+++ b/test/trace_processor/graphics/gpu_frequency_metric.out
@@ -0,0 +1,39 @@
+android_gpu {
+ freq_metrics {
+ gpu_id: 0
+ freq_max: 603000
+ freq_min: 0
+ freq_avg: 475200.0 # = (585000 * 2 + 0 * 1 + 603000 * 2) / 5
+ used_freqs {
+ freq: 0
+ dur_ms: 1.0
+ percentage: 20.0
+ }
+ used_freqs {
+ freq: 585000
+ dur_ms: 2.0
+ percentage: 40.0
+ }
+ used_freqs {
+ freq: 603000
+ dur_ms: 2.0
+ percentage: 40.0
+ }
+ }
+ freq_metrics {
+ gpu_id: 1
+ freq_max: 758000
+ freq_min: 400000
+ freq_avg: 489500.0 # = (400000 * 3 + 758000 * 1) / 4
+ used_freqs {
+ freq: 400000
+ dur_ms: 3.0
+ percentage: 75.0
+ }
+ used_freqs {
+ freq: 758000
+ dur_ms: 1.0
+ percentage: 25.0
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/trace_processor/graphics/gpu_frequency_metric.textproto b/test/trace_processor/graphics/gpu_frequency_metric.textproto
new file mode 100644
index 0000000..8f0710f
--- /dev/null
+++ b/test/trace_processor/graphics/gpu_frequency_metric.textproto
@@ -0,0 +1,55 @@
+packet {
+ ftrace_events {
+ cpu: 0
+ event {
+ timestamp: 200001000000
+ pid: 527
+ gpu_frequency {
+ gpu_id: 0
+ state: 585000
+ }
+ }
+ event {
+ timestamp: 200002000000
+ pid: 527
+ gpu_frequency {
+ gpu_id: 1
+ state: 400000
+ }
+ }
+ event {
+ timestamp: 200003000000
+ pid: 527
+ gpu_frequency {
+ gpu_id: 0
+ state: 0
+ }
+ }
+ event {
+ timestamp: 200004000000
+ pid: 527
+ gpu_frequency {
+ gpu_id: 0
+ state: 603000
+ }
+ }
+ event {
+ timestamp: 200005000000
+ pid: 527
+ gpu_frequency {
+ gpu_id: 1
+ state: 758000
+ }
+ }
+ event {
+ timestamp: 200005999999
+ pid: 527
+ gpu_frequency {
+ gpu_id: 0
+ state: 603000
+ }
+ }
+ }
+ trusted_uid: 9999
+ trusted_packet_sequence_id: 2
+}
\ No newline at end of file
diff --git a/test/trace_processor/graphics/gpu_mem_total.py b/test/trace_processor/graphics/gpu_mem_total.py
index e21d8a8..5157bc8 100755
--- a/test/trace_processor/graphics/gpu_mem_total.py
+++ b/test/trace_processor/graphics/gpu_mem_total.py
@@ -25,15 +25,15 @@
# 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)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=0, pid=0, ts=5, size=256)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=0, 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)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=1, pid=1, ts=5, size=233)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=1, pid=1, ts=10, size=0)
sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_mem_total_after_free.py b/test/trace_processor/graphics/gpu_mem_total_after_free.py
new file mode 100644
index 0000000..2b68d4c
--- /dev/null
+++ b/test/trace_processor/graphics/gpu_mem_total_after_free.py
@@ -0,0 +1,38 @@
+#!/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()
+
+# 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(ftrace_pid=1, pid=1, ts=5, size=233)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=1, pid=1, ts=10, size=50)
+
+# Finish the process at ts = 12
+trace.add_process_free(ts=12, tid=1, comm="app", prio=10)
+
+# Emit another event now at ts = 15 - this should be ignored
+# (see b/192274404 for more info).
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=0, pid=1, ts=15, size=0)
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_mem_total_after_free_gpu_mem_total.out b/test/trace_processor/graphics/gpu_mem_total_after_free_gpu_mem_total.out
new file mode 100644
index 0000000..b88ad31
--- /dev/null
+++ b/test/trace_processor/graphics/gpu_mem_total_after_free_gpu_mem_total.out
@@ -0,0 +1,4 @@
+"name","unit","description","ts","pid","value"
+"GPU Memory","7","Total GPU memory used by this process",0,1,100
+"GPU Memory","7","Total GPU memory used by this process",5,1,233
+"GPU Memory","7","Total GPU memory used by this process",10,1,50
diff --git a/test/trace_processor/graphics/gpu_metric.py b/test/trace_processor/graphics/gpu_metric.py
index 8179d08..e7dfb3b 100644
--- a/test/trace_processor/graphics/gpu_metric.py
+++ b/test/trace_processor/graphics/gpu_metric.py
@@ -26,21 +26,21 @@
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)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=0, pid=0, ts=2, size=1)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=0, pid=0, ts=4, size=2)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=0, 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)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=1, pid=1, ts=4, size=2)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=1, 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)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=2, pid=2, ts=2, size=6)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=2, 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)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=3, pid=3, ts=6, size=7)
+trace.add_gpu_mem_total_ftrace_event(ftrace_pid=3, pid=3, ts=7, size=10)
# app_2 will be aggregated
# max=10, min=6, avg=(60+37)/(8+4)=8
diff --git a/test/trace_processor/graphics/index b/test/trace_processor/graphics/index
index c479dea..34cc136 100644
--- a/test/trace_processor/graphics/index
+++ b/test/trace_processor/graphics/index
@@ -13,16 +13,19 @@
# GPU Memory ftrace packets
gpu_mem_total.py gpu_mem_total.sql gpu_mem_total.out
+gpu_mem_total_after_free.py gpu_mem_total.sql gpu_mem_total_after_free_gpu_mem_total.out
# Clock sync
clock_sync.py clock_sync.sql clock_sync.out
-# Missed frames
+# Android SurfaceFlinger metrics
frame_missed.py frame_missed_event.sql frame_missed_event_frame_missed.out
frame_missed.py android_surfaceflinger frame_missed_metrics.out
+surfaceflinger_gpu_invocation.py android_surfaceflinger surfaceflinger_gpu_invocation.out
# GPU metrics
gpu_metric.py android_gpu gpu_metric.out
+gpu_frequency_metric.textproto android_gpu gpu_frequency_metric.out
# Android SysUI CUJs metrics
android_sysui_cuj.py android_sysui_cuj android_sysui_cuj.out
@@ -46,3 +49,6 @@
# Display metrics
panel_fps.py display_metrics panel_fps.out
+
+# DPU vote clock and bandwidth
+dpu_vote_clock_bw.textproto android_hwcomposer dpu_vote_clock_bw.out
diff --git a/test/trace_processor/graphics/surfaceflinger_gpu_invocation.out b/test/trace_processor/graphics/surfaceflinger_gpu_invocation.out
new file mode 100644
index 0000000..9495fed
--- /dev/null
+++ b/test/trace_processor/graphics/surfaceflinger_gpu_invocation.out
@@ -0,0 +1,8 @@
+android_surfaceflinger {
+ missed_frames: 0
+ missed_hwc_frames: 0
+ missed_gpu_frames: 0
+ gpu_invocations: 4
+ avg_gpu_waiting_dur_ms: 4
+ total_non_empty_gpu_waiting_dur_ms: 11
+}
diff --git a/test/trace_processor/graphics/surfaceflinger_gpu_invocation.py b/test/trace_processor/graphics/surfaceflinger_gpu_invocation.py
new file mode 100644
index 0000000..53c6326
--- /dev/null
+++ b/test/trace_processor/graphics/surfaceflinger_gpu_invocation.py
@@ -0,0 +1,51 @@
+#!/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(pid=10, ppid=1, cmdline='/system/bin/surfaceflinger', uid=None)
+trace.add_thread(tid=10, tgid=10, cmdline='', name='Main thread')
+trace.add_thread(tid=33, tgid=10, cmdline='', name='GPU completion')
+trace.add_ftrace_packet(1)
+
+trace.add_atrace_begin(ts=1_000_000, tid=33, pid=10, buf='waiting for GPU completion 4')
+trace.add_atrace_end(ts=2_000_000, tid=33, pid=10)
+
+trace.add_atrace_begin(ts=3_000_000, tid=10, pid=10, buf='Trace GPU completion fence 5')
+trace.add_atrace_begin(ts=3_000_000, tid=33, pid=10, buf='waiting for GPU completion 5')
+trace.add_atrace_end(ts=3_000_500, tid=10, pid=10)
+trace.add_atrace_end(ts=6_000_000, tid=33, pid=10)
+
+trace.add_atrace_begin(ts=7_000_000, tid=10, pid=10, buf='Trace GPU completion fence 6')
+trace.add_atrace_begin(ts=7_000_000, tid=33, pid=10, buf='waiting for GPU completion 6')
+trace.add_atrace_end(ts=7_000_500, tid=10, pid=10)
+trace.add_atrace_begin(ts=10_000_000, tid=10, pid=10, buf='Trace GPU completion fence 7')
+trace.add_atrace_end(ts=10_000_500, tid=10, pid=10)
+trace.add_atrace_end(ts=12_000_000, tid=33, pid=10)
+trace.add_atrace_begin(ts=12_000_000, tid=33, pid=10, buf='waiting for GPU completion 7')
+trace.add_atrace_end(ts=14_000_000, tid=33, pid=10)
+
+trace.add_atrace_begin(ts=15_000_000, tid=10, pid=10, buf='Trace GPU completion fence 8')
+trace.add_atrace_end(ts=15_000_500, tid=10, pid=10)
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/memory/android_systrace_lmk.py b/test/trace_processor/memory/android_systrace_lmk.py
new file mode 100644
index 0000000..472a0cc
--- /dev/null
+++ b/test/trace_processor/memory/android_systrace_lmk.py
@@ -0,0 +1,31 @@
+#!/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, 'lmkd')
+trace.add_process(3, 1, 'com.google.android.calendar')
+
+trace.add_ftrace_packet(cpu=0)
+trace.add_oom_score_update(ts=100, oom_score_adj=0, pid=3)
+trace.add_atrace_begin(ts=100000, pid=1, tid=1, buf='lmk,3,1,900')
+trace.add_atrace_end(ts=100001, pid=1, tid=1)
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/memory/index b/test/trace_processor/memory/index
index 683d4f1..b8a527b 100644
--- a/test/trace_processor/memory/index
+++ b/test/trace_processor/memory/index
@@ -5,6 +5,7 @@
../../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_systrace_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
diff --git a/test/trace_processor/memory/trace_metadata.out b/test/trace_processor/memory/trace_metadata.out
index b66bf1a..1f64280 100644
--- a/test/trace_processor/memory/trace_metadata.out
+++ b/test/trace_processor/memory/trace_metadata.out
@@ -1,5 +1,6 @@
trace_metadata {
trace_duration_ns: 9519159074,
+ trace_uuid: "00000000-0000-0000-e77f-20a2204c2a49",
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/android_log_msgs.sql b/test/trace_processor/parsing/android_log_msgs.sql
index dfbd6a3..02093ca 100644
--- a/test/trace_processor/parsing/android_log_msgs.sql
+++ b/test/trace_processor/parsing/android_log_msgs.sql
@@ -13,7 +13,7 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-create view v1 as select tag, count(*) from android_logs group by tag order by 2 desc limit 5
+create view v1 as select tag, count(*) from android_logs group by tag order by 2 desc limit 5;
create view v2 as select tag, count(*) from android_logs group by tag order by 2 asc limit 5;
@@ -27,4 +27,4 @@
select '-----', 0 union all
select * from v3 union all
select '-----', 0 union all
-select * from v4;
\ No newline at end of file
+select * from v4;
diff --git a/test/trace_processor/parsing/android_multiuser_switch.out b/test/trace_processor/parsing/android_multiuser_switch.out
new file mode 100644
index 0000000..a49f9e3
--- /dev/null
+++ b/test/trace_processor/parsing/android_multiuser_switch.out
@@ -0,0 +1,5 @@
+android_multiuser: {
+ user_switch: {
+ duration_ms: 4900
+ }
+}
\ No newline at end of file
diff --git a/test/trace_processor/parsing/android_multiuser_switch.textproto b/test/trace_processor/parsing/android_multiuser_switch.textproto
new file mode 100644
index 0000000..223ddb6
--- /dev/null
+++ b/test/trace_processor/parsing/android_multiuser_switch.textproto
@@ -0,0 +1,48 @@
+packet {
+ ftrace_events {
+ cpu: 3
+ event {
+ timestamp: 3000000000 # 3e9
+ pid: 4064
+ print {
+ buf: "S|1204|onBeforeStartUser-10|0\n"
+ }
+ }
+ }
+}
+packet {
+ ftrace_events {
+ cpu: 3
+ event {
+ timestamp: 3100000000
+ pid: 4064
+ print {
+ buf: "F|1204|onBeforeStartUser-10|0\n"
+ }
+ }
+ }
+}
+packet {
+ ftrace_events {
+ cpu: 2
+ event {
+ timestamp: 5200000000
+ pid: 4065
+ print {
+ buf: "S|1204|launching: com.google.android.apps.nexuslauncher|0\n"
+ }
+ }
+ }
+}
+packet {
+ ftrace_events {
+ cpu: 2
+ event {
+ timestamp: 7900000000 # 7.9e9
+ pid: 4065
+ print {
+ buf: "F|1204|launching: com.google.android.apps.nexuslauncher|0\n"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/trace_processor/parsing/b120487929.sql b/test/trace_processor/parsing/b120487929.sql
index 179d324..a266d7a 100644
--- a/test/trace_processor/parsing/b120487929.sql
+++ b/test/trace_processor/parsing/b120487929.sql
@@ -38,19 +38,19 @@
where name = 'cpuidle';
create virtual table freq_idle
- using span_join(freq_view PARTITIONED cpu, idle_view PARTITIONED cpu)
+ using span_join(freq_view PARTITIONED cpu, idle_view PARTITIONED cpu);
create virtual table window_freq_idle using window;
create virtual table span_freq_idle
- using span_join(freq_idle PARTITIONED cpu, window_freq_idle)
+ using span_join(freq_idle PARTITIONED cpu, window_freq_idle);
update window_freq_idle
set
window_start=(select min(ts) from sched),
window_dur=(select max(ts) - min(ts) from sched),
quantum=1000000
- where rowid = 0
+ where rowid = 0;
create view counter_view
as select
@@ -66,6 +66,6 @@
when 4294967295 then freq_value
else idle_value
end as value
- from span_freq_idle
+ from span_freq_idle;
-select cpu, name, value, sum(dur) from counter_view group by cpu, name, value
+select cpu, name, value, sum(dur) from counter_view group by cpu, name, value;
diff --git a/test/trace_processor/parsing/cgroup_attach_task_post_s.textproto b/test/trace_processor/parsing/cgroup_attach_task_post_s.textproto
new file mode 100644
index 0000000..6950e5a
--- /dev/null
+++ b/test/trace_processor/parsing/cgroup_attach_task_post_s.textproto
@@ -0,0 +1,17 @@
+packet {
+ ftrace_events {
+ cpu: 3
+ event {
+ timestamp: 74289018336
+ pid: 1
+ cgroup_attach_task {
+ dst_root: 1
+ dst_id: 2
+ pid: 3
+ comm: "foo"
+ dst_level: 4
+ dst_path: "bar"
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/test/trace_processor/parsing/cgroup_attach_task_post_s_print_systrace.out b/test/trace_processor/parsing/cgroup_attach_task_post_s_print_systrace.out
new file mode 100644
index 0000000..5d47364
--- /dev/null
+++ b/test/trace_processor/parsing/cgroup_attach_task_post_s_print_systrace.out
@@ -0,0 +1,2 @@
+"to_ftrace(id)"
+" <unknown>-1 (-----) [003] .... 74.289018: cgroup_attach_task: dst_root=1 dst_id=2 dst_level=4 dst_path=bar pid=3 comm=foo"
diff --git a/test/trace_processor/parsing/cgroup_attach_task_pre_s.textproto b/test/trace_processor/parsing/cgroup_attach_task_pre_s.textproto
new file mode 100644
index 0000000..679b211
--- /dev/null
+++ b/test/trace_processor/parsing/cgroup_attach_task_pre_s.textproto
@@ -0,0 +1,16 @@
+packet {
+ ftrace_events {
+ cpu: 3
+ event {
+ timestamp: 74289018336
+ pid: 1
+ cgroup_attach_task {
+ dst_root: 1
+ dst_id: 2
+ pid: 3
+ comm: "foo"
+ cname: "bar"
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/test/trace_processor/parsing/cgroup_attach_task_pre_s_print_systrace.out b/test/trace_processor/parsing/cgroup_attach_task_pre_s_print_systrace.out
new file mode 100644
index 0000000..e7d5df7
--- /dev/null
+++ b/test/trace_processor/parsing/cgroup_attach_task_pre_s_print_systrace.out
@@ -0,0 +1,2 @@
+"to_ftrace(id)"
+" <unknown>-1 (-----) [003] .... 74.289018: cgroup_attach_task: dst_root=1 dst_id=2 cgroup=bar pid=3 comm=foo"
diff --git a/test/trace_processor/parsing/chrome_metadata.out b/test/trace_processor/parsing/chrome_metadata.out
index 71e8908..ffdc373 100644
--- a/test/trace_processor/parsing/chrome_metadata.out
+++ b/test/trace_processor/parsing/chrome_metadata.out
@@ -1,4 +1,5 @@
"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]"
+0,"metadata","trace_uuid","single","[NULL]","00000000-0000-0000-23b6-9c184f48509d"
+1,"metadata","cr-playstore_version_code","single",101,"[NULL]"
+2,"metadata","cr-enabled_categories","single","[NULL]","cat1,cat2,cat3"
+3,"metadata","trace_size_bytes","single",50,"[NULL]"
diff --git a/test/trace_processor/parsing/flow_events_json_v2.json b/test/trace_processor/parsing/flow_events_json_v2.json
index f62e86d..7b53b67 100644
--- a/test/trace_processor/parsing/flow_events_json_v2.json
+++ b/test/trace_processor/parsing/flow_events_json_v2.json
@@ -10,7 +10,9 @@
"args":{},
"dur": 10,
"bind_id": "0x402",
- "flow_out": true
+ "flow_out": true,
+ "tts":3005,
+ "tdur":7
},
{
"cat": "ipc",
@@ -23,7 +25,9 @@
"dur": 10,
"bind_id": "0x403",
"flow_out": true,
- "flow_in": false
+ "flow_in": false,
+ "tts":1,
+ "tdur":5
},
{
"cat": "ipc",
@@ -48,7 +52,9 @@
"dur": 500,
"bind_id": "0x402",
"flow_in": true,
- "flow_out": true
+ "flow_out": true,
+ "tts":3204,
+ "tdur":100
},
{
"cat": "ipc",
@@ -60,7 +66,9 @@
"args": {},
"dur": 400,
"bind_id": "0x402",
- "flow_in": true
+ "flow_in": true,
+ "tts":3335,
+ "tdur":340
},
{
"cat": "ipc",
@@ -71,7 +79,18 @@
"name": "SomeOtherSlice",
"args": {},
"bind_id": "0x402",
- "flow_in": true
+ "flow_in": true,
+ "tts":3335
+ },
+ {
+ "cat": "ipc",
+ "pid": 15875,
+ "tid": 15895,
+ "ts": 3366,
+ "dur": 0,
+ "ph": "i",
+ "name": "SomeOtherSliceInstant",
+ "args": {}
},
{
"cat": "ipc",
@@ -80,7 +99,8 @@
"ts": 4330,
"ph": "E",
"name": "SomeOtherSlice",
+ "tts":4331,
"args": {}
}
]
- }
\ No newline at end of file
+ }
diff --git a/test/trace_processor/parsing/index b/test/trace_processor/parsing/index
index 65ef807..b586e28 100644
--- a/test/trace_processor/parsing/index
+++ b/test/trace_processor/parsing/index
@@ -63,9 +63,14 @@
# 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
+kernel_dpu_tmw_counter.textproto thread_counter_and_track.sql kernel_dpu_tmw_counter_thread_counter_and_track.out
# Unsigned integers
print_systrace_unsigned.py print_systrace.sql print_systrace_unsigned.out
+# cgroup_attach_task systrace conversion.
+cgroup_attach_task_pre_s.textproto print_systrace.sql cgroup_attach_task_pre_s_print_systrace.out
+cgroup_attach_task_post_s.textproto print_systrace.sql cgroup_attach_task_post_s_print_systrace.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
@@ -104,6 +109,9 @@
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
+# thread_slice tables.
+flow_events_json_v2.json thread_time_in_thread_slice.sql thread_time_in_thread_slice.out
+
# Initial display state
initial_display_state.textproto initial_display_state.sql initial_display_state.out
@@ -146,3 +154,12 @@
# JSON instants and counters
../../data/counters.json json_counters.sql counters_json_counters.out
../../data/instants.json json_instants.sql instants_json_instants.out
+
+# Trace quality metric
+very_long_sched.py android_trace_quality very_long_sched_android_trace_quality.out
+
+# Regression test for b/193721088 (infra prepending " done\n" to atrace)
+../../data/atrace_b_193721088.atr sched_smoke.sql sched_smoke_trailing_empty.out
+
+# Multiuser
+android_multiuser_switch.textproto android_multiuser android_multiuser_switch.out
diff --git a/test/trace_processor/parsing/kernel_dpu_tmw_counter.textproto b/test/trace_processor/parsing/kernel_dpu_tmw_counter.textproto
new file mode 100644
index 0000000..32bd0cf
--- /dev/null
+++ b/test/trace_processor/parsing/kernel_dpu_tmw_counter.textproto
@@ -0,0 +1,47 @@
+packet {
+ ftrace_events {
+ cpu: 2
+ event {
+ timestamp: 795572805481
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_clock"
+ type: 67
+ value: 123
+ }
+ }
+ event {
+ timestamp: 795572870504
+ pid: 515
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_clock"
+ type: 67
+ value: 100
+ }
+ }
+ event {
+ timestamp: 795620516581
+ pid: 237
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_clock"
+ type: 67
+ value: 125
+ }
+ }
+ event {
+ timestamp: 795620943421
+ pid: 515
+ dpu_tracing_mark_write {
+ pid: 237
+ name: "dpu_vote_clock"
+ type: 67
+ value: 100
+ }
+ }
+ }
+ trusted_uid: 9999
+ trusted_packet_sequence_id: 3
+}
\ No newline at end of file
diff --git a/test/trace_processor/parsing/kernel_dpu_tmw_counter_thread_counter_and_track.out b/test/trace_processor/parsing/kernel_dpu_tmw_counter_thread_counter_and_track.out
new file mode 100644
index 0000000..683b8da
--- /dev/null
+++ b/test/trace_processor/parsing/kernel_dpu_tmw_counter_thread_counter_and_track.out
@@ -0,0 +1,5 @@
+"ts","name","value","tid"
+795572805481,"dpu_vote_clock",123.000000,237
+795572870504,"dpu_vote_clock",100.000000,237
+795620516581,"dpu_vote_clock",125.000000,237
+795620943421,"dpu_vote_clock",100.000000,237
diff --git a/test/trace_processor/parsing/thread_time_in_state_event.out b/test/trace_processor/parsing/thread_time_in_state_event.out
index af8192c..f71fd29 100644
--- a/test/trace_processor/parsing/thread_time_in_state_event.out
+++ b/test/trace_processor/parsing/thread_time_in_state_event.out
@@ -1,13 +1,13 @@
-"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
+"track_type","track_name","upid","ts","value"
+"counter","Total big core mcycles",0,2000000000,1.100000
+"counter","Total little core mcycles",0,2000000000,1.100000
+"counter","Thread 10 (1) (big core) mcycles",1,2000000000,1.100000
+"counter","Thread 10 (1) (little core) mcycles",1,2000000000,1.100000
+"counter","Total big core mcycles",0,3000000000,23.100000
+"counter","Total little core mcycles",0,3000000000,23.100000
+"counter","Thread 10 (1) (big core) mcycles",1,3000000000,23.100000
+"counter","Thread 10 (1) (little core) mcycles",1,3000000000,23.100000
+"counter","Thread 20 (3) (big core) mcycles",2,3000000000,11.000000
+"counter","Thread 20 (3) (little core) mcycles",2,3000000000,11.000000
+"counter","Thread 40 (7) (little core) mcycles",4,3000000000,0.100000
diff --git a/test/trace_processor/parsing/thread_time_in_thread_slice.out b/test/trace_processor/parsing/thread_time_in_thread_slice.out
new file mode 100644
index 0000000..1be6304
--- /dev/null
+++ b/test/trace_processor/parsing/thread_time_in_thread_slice.out
@@ -0,0 +1,8 @@
+"name","thread_ts","thread_dur"
+"SenderB",1000,5000
+"Blergh","[NULL]","[NULL]"
+"SenderA",3005000,7000
+"OtherSlice",3204000,100000
+"SomeSlice",3335000,340000
+"SomeOtherSlice",3335000,996000
+"SomeOtherSliceInstant","[NULL]","[NULL]"
diff --git a/test/trace_processor/parsing/thread_time_in_thread_slice.sql b/test/trace_processor/parsing/thread_time_in_thread_slice.sql
new file mode 100644
index 0000000..207376b
--- /dev/null
+++ b/test/trace_processor/parsing/thread_time_in_thread_slice.sql
@@ -0,0 +1,3 @@
+SELECT
+ name, thread_ts, thread_dur
+FROM thread_slice;
diff --git a/test/trace_processor/parsing/very_long_sched.py b/test/trace_processor/parsing/very_long_sched.py
new file mode 100644
index 0000000..878fcd2
--- /dev/null
+++ b/test/trace_processor/parsing/very_long_sched.py
@@ -0,0 +1,34 @@
+#!/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_packet(ts=1)
+trace.add_process(10, 0, "processa")
+trace.add_process(20, 0, "processb")
+
+trace.add_ftrace_packet(0)
+
+# Add a very long (~1 month long) sched slice.
+trace.add_sched(ts=50, prev_pid=10, next_pid=20)
+
+end_ts = 1 * 30 * 24 * 60 * 60 * 60 * 1000 * 1000 * 1000
+trace.add_sched(ts=end_ts, prev_pid=20, next_pid=10)
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/very_long_sched_android_trace_quality.out b/test/trace_processor/parsing/very_long_sched_android_trace_quality.out
new file mode 100644
index 0000000..3c0537c
--- /dev/null
+++ b/test/trace_processor/parsing/very_long_sched_android_trace_quality.out
@@ -0,0 +1,5 @@
+android_trace_quality {
+ failures {
+ name: "sched_slice_too_long"
+ }
+}
\ No newline at end of file
diff --git a/test/trace_processor/profiling/callstack_sampling_flamegraph.out b/test/trace_processor/profiling/callstack_sampling_flamegraph.out
new file mode 100644
index 0000000..f98a857
--- /dev/null
+++ b/test/trace_processor/profiling/callstack_sampling_flamegraph.out
@@ -0,0 +1,11 @@
+"id","type","depth","name","map_name","count","cumulative_count","size","cumulative_size","alloc_count","cumulative_alloc_count","alloc_size","cumulative_alloc_size","parent_id","source_file","line_number"
+0,"experimental_flamegraph_nodes",0,"__start_thread","/apex/com.android.runtime/lib64/bionic/libc.so",0,560,0,560,0,0,0,0,"[NULL]","[NULL]","[NULL]"
+1,"experimental_flamegraph_nodes",1,"_ZL15__pthread_startPv","/apex/com.android.runtime/lib64/bionic/libc.so",0,560,0,560,0,0,0,0,0,"[NULL]","[NULL]"
+2,"experimental_flamegraph_nodes",2,"_ZN3art6Thread14CreateCallbackEPv","/apex/com.android.art/lib64/libart.so",0,301,0,301,0,0,0,0,1,"[NULL]","[NULL]"
+3,"experimental_flamegraph_nodes",3,"_ZN3art35InvokeVirtualOrInterfaceWithJValuesIPNS_9ArtMethodEEENS_6JValueERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectT_PK6jvalue","/apex/com.android.art/lib64/libart.so",0,301,0,301,0,0,0,0,2,"[NULL]","[NULL]"
+4,"experimental_flamegraph_nodes",4,"_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc","/apex/com.android.art/lib64/libart.so",0,301,0,301,0,0,0,0,3,"[NULL]","[NULL]"
+5,"experimental_flamegraph_nodes",5,"art_quick_invoke_stub","/apex/com.android.art/lib64/libart.so",0,301,0,301,0,0,0,0,4,"[NULL]","[NULL]"
+6,"experimental_flamegraph_nodes",6,"android.os.HandlerThread.run","/system/framework/arm64/boot-framework.oat",0,43,0,43,0,0,0,0,5,"[NULL]","[NULL]"
+7,"experimental_flamegraph_nodes",7,"android.os.Looper.loop","/system/framework/arm64/boot-framework.oat",0,43,0,43,0,0,0,0,6,"[NULL]","[NULL]"
+8,"experimental_flamegraph_nodes",8,"android.os.Looper.loopOnce","/system/framework/arm64/boot-framework.oat",1,43,1,43,0,0,0,0,7,"[NULL]","[NULL]"
+9,"experimental_flamegraph_nodes",9,"android.os.Handler.dispatchMessage","/system/framework/arm64/boot-framework.oat",0,35,0,35,0,0,0,0,8,"[NULL]","[NULL]"
diff --git a/test/trace_processor/profiling/callstack_sampling_flamegraph.sql b/test/trace_processor/profiling/callstack_sampling_flamegraph.sql
new file mode 100644
index 0000000..f9da1da
--- /dev/null
+++ b/test/trace_processor/profiling/callstack_sampling_flamegraph.sql
@@ -0,0 +1,5 @@
+select * from experimental_flamegraph
+where upid = 30
+ and profile_type = 'perf'
+ and ts <= 7689491063351
+limit 10;
diff --git a/test/trace_processor/profiling/index b/test/trace_processor/profiling/index
index 66ae8e4..f594f4f 100644
--- a/test/trace_processor/profiling/index
+++ b/test/trace_processor/profiling/index
@@ -8,6 +8,7 @@
profiler_smaps.textproto profiler_smaps.sql profiler_smaps.out
+profiler_smaps.textproto profiler_smaps profiler_smaps_metric.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
@@ -51,3 +52,4 @@
# 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
+../../data/callstack_sampling.pftrace callstack_sampling_flamegraph.sql callstack_sampling_flamegraph.out
diff --git a/test/trace_processor/profiling/profiler_smaps_metric.out b/test/trace_processor/profiling/profiler_smaps_metric.out
new file mode 100644
index 0000000..1c83553
--- /dev/null
+++ b/test/trace_processor/profiling/profiler_smaps_metric.out
@@ -0,0 +1,20 @@
+profiler_smaps {
+ instance {
+ process {
+ name: "system_server"
+ uid: 1000
+ }
+ mappings {
+ path: "[anon: libc_malloc]"
+ size_kb: 30
+ private_dirty_kb: 10
+ swap_kb: 10
+ }
+ mappings {
+ path: "/system/lib64/libc.so"
+ size_kb: 20
+ private_dirty_kb: 4
+ swap_kb: 4
+ }
+ }
+}
diff --git a/test/trace_processor/python/api_unittest.py b/test/trace_processor/python/api_unittest.py
index 9feada4..29abd5f 100755
--- a/test/trace_processor/python/api_unittest.py
+++ b/test/trace_processor/python/api_unittest.py
@@ -25,6 +25,7 @@
CELL_VARINT = ProtoFactory().CellsBatch().CELL_VARINT
CELL_STRING = ProtoFactory().CellsBatch().CELL_STRING
CELL_INVALID = ProtoFactory().CellsBatch().CELL_INVALID
+ CELL_NULL = ProtoFactory().CellsBatch().CELL_NULL
def test_one_batch(self):
int_values = [100, 200]
@@ -34,18 +35,22 @@
batch.cells.extend([
TestQueryResultIterator.CELL_STRING,
TestQueryResultIterator.CELL_VARINT,
- TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
+ TestQueryResultIterator.CELL_NULL,
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_NULL,
])
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_iterator = TraceProcessor.QueryResultIterator(
+ ['foo_id', 'foo_num', 'foo_null'], [batch])
for num, row in enumerate(qr_iterator):
self.assertEqual(row.foo_id, str_values[num])
self.assertEqual(row.foo_num, int_values[num])
+ self.assertEqual(row.foo_null, None)
def test_many_batches(self):
int_values = [100, 200, 300, 400]
@@ -55,7 +60,10 @@
batch_1.cells.extend([
TestQueryResultIterator.CELL_STRING,
TestQueryResultIterator.CELL_VARINT,
- TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
+ TestQueryResultIterator.CELL_NULL,
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_NULL,
])
batch_1.varint_cells.extend(int_values[:2])
batch_1.string_cells = "\0".join(str_values[:2]) + "\0"
@@ -65,18 +73,22 @@
batch_2.cells.extend([
TestQueryResultIterator.CELL_STRING,
TestQueryResultIterator.CELL_VARINT,
- TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
+ TestQueryResultIterator.CELL_NULL,
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_NULL,
])
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_iterator = TraceProcessor.QueryResultIterator(
+ ['foo_id', 'foo_num', 'foo_null'], [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])
+ self.assertEqual(row.foo_null, None)
def test_empty_batch(self):
batch = ProtoFactory().CellsBatch()
@@ -91,13 +103,42 @@
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
+ qr_iterator = TraceProcessor.QueryResultIterator([], [batch])
+
+ def test_null_cells(self):
+ int_values = [100, 200, 300, 500, 600]
+ str_values = ['bar1', 'bar2', 'bar3']
+
+ batch = ProtoFactory().CellsBatch()
+ batch.cells.extend([
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_NULL,
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ 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', 'foo_num_2'], [batch])
+
+ # Any cell (and thus column in a row) can be set to null
+ # In this query result, foo_num_2 of row 2 was set to null
+ # Test to see that all the rows are still returned correctly
+ int_values_check = [100, 200, 300, None, 500, 600]
+ for num, row in enumerate(qr_iterator):
+ self.assertEqual(row.foo_id, str_values[num])
+ self.assertEqual(row.foo_num, int_values_check[num * 2])
+ self.assertEqual(row.foo_num_2, int_values_check[num * 2 + 1])
def test_incorrect_cells_batch(self):
str_values = ['bar1', 'bar2']
@@ -129,16 +170,12 @@
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
+ # of columns. However, here this is clearly not the case, so raise a
+ # TraceProcessorException during the data integrity check in the constructor
+ with self.assertRaises(TraceProcessorException):
+ qr_iterator = TraceProcessor.QueryResultIterator(
+ ['foo_id', 'foo_num', 'foo_dur', 'foo_ms'], [batch])
def test_invalid_cell_type(self):
batch = ProtoFactory().CellsBatch()
@@ -167,19 +204,23 @@
batch.cells.extend([
TestQueryResultIterator.CELL_STRING,
TestQueryResultIterator.CELL_VARINT,
- TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
+ TestQueryResultIterator.CELL_NULL,
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_NULL,
])
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_iterator = TraceProcessor.QueryResultIterator(
+ ['foo_id', 'foo_num', 'foo_null'], [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])
+ self.assertEqual(row['foo_null'], None)
def test_many_batches_as_pandas(self):
int_values = [100, 200, 300, 400]
@@ -189,7 +230,10 @@
batch_1.cells.extend([
TestQueryResultIterator.CELL_STRING,
TestQueryResultIterator.CELL_VARINT,
- TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
+ TestQueryResultIterator.CELL_NULL,
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_NULL,
])
batch_1.varint_cells.extend(int_values[:2])
batch_1.string_cells = "\0".join(str_values[:2]) + "\0"
@@ -199,19 +243,23 @@
batch_2.cells.extend([
TestQueryResultIterator.CELL_STRING,
TestQueryResultIterator.CELL_VARINT,
- TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
+ TestQueryResultIterator.CELL_NULL,
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_NULL,
])
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_iterator = TraceProcessor.QueryResultIterator(
+ ['foo_id', 'foo_num', 'foo_null'], [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])
+ self.assertEqual(row['foo_null'], None)
def test_empty_batch_as_pandas(self):
batch = ProtoFactory().CellsBatch()
@@ -224,15 +272,38 @@
self.assertEqual(row['foo_id'], str_values[num])
self.assertEqual(row['foo_num'], int_values[num])
- def test_invalid_batch_as_pandas(self):
+ def test_null_cells_as_pandas(self):
+ int_values = [100, 200, 300, 500, 600]
+ str_values = ['bar1', 'bar2', 'bar3']
+
batch = ProtoFactory().CellsBatch()
+ batch.cells.extend([
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ TestQueryResultIterator.CELL_NULL,
+ TestQueryResultIterator.CELL_STRING,
+ TestQueryResultIterator.CELL_VARINT,
+ 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([], [batch])
+ qr_iterator = TraceProcessor.QueryResultIterator(
+ ['foo_id', 'foo_num', 'foo_num_2'], [batch])
+ qr_df = qr_iterator.as_pandas_dataframe()
- # 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()
+ # Any cell (and thus column in a row) can be set to null
+ # In this query result, foo_num_2 of row 2 was set to null
+ # Test to see that all the rows are still returned correctly
+ int_values_check = [100, 200, 300, None, 500, 600]
+ for num, row in qr_df.iterrows():
+ self.assertEqual(row['foo_id'], str_values[num])
+ self.assertEqual(row['foo_num'], int_values_check[num * 2])
+ self.assertEqual(row['foo_num_2'], int_values_check[num * 2 + 1])
def test_incorrect_cells_batch_as_pandas(self):
str_values = ['bar1', 'bar2']
@@ -255,24 +326,6 @@
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([
diff --git a/test/trace_processor/startup/android_startup_attribution.out b/test/trace_processor/startup/android_startup_attribution.out
index 5046ed4..87b1a30 100644
--- a/test/trace_processor/startup/android_startup_attribution.out
+++ b/test/trace_processor/startup/android_startup_attribution.out
@@ -56,6 +56,9 @@
dur_ms: 100
}
thread: "Binder"
+ destination_process: "system_server"
+ flags: "0x00 No Flags Set"
+ code: "0x00 Java Layer Dependent"
}
long_binder_transactions {
duration {
@@ -63,6 +66,10 @@
dur_ms: 200
}
thread: "fonts"
+ destination_thread: "Binder"
+ destination_process: "com.some.app"
+ flags: "0x00 No Flags Set"
+ code: "0x00 Java Layer Dependent"
}
}
}
diff --git a/test/trace_processor/startup/android_startup_attribution.py b/test/trace_processor/startup/android_startup_attribution.py
index 61d9ebc..cf3ab8e 100644
--- a/test/trace_processor/startup/android_startup_attribution.py
+++ b/test/trace_processor/startup/android_startup_attribution.py
@@ -150,18 +150,18 @@
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_binder_transaction(1, 10**8, 2 * (10**8), BINDER_TID, APP_PID, 2,
+ 10**8 + 1, 2 * (10**8) - 1, SYSTEM_SERVER_TID,
+ SYSTEM_SERVER_PID)
-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)
+trace.add_binder_transaction(3, 3 * (10**8), 5 * (10**8), FONTS_TID, APP_PID, 4,
+ 3 * (10**8) + 1, 5 * (10**8) - 1, BINDER_TID,
+ APP_PID)
# 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)
+trace.add_binder_transaction(5, 10**7, 5 * (10**7), BINDER_TID, APP_TID, 6,
+ 10**7 + 1, 5 * (10**7) - 1, SYSTEM_SERVER_TID,
+ SYSTEM_SERVER_PID)
# Intent successful.
trace.add_atrace_begin(
diff --git a/test/trace_processor/startup/android_startup_powrails.out b/test/trace_processor/startup/android_startup_powrails.out
index 67d5677..3c26381 100644
--- a/test/trace_processor/startup/android_startup_powrails.out
+++ b/test/trace_processor/startup/android_startup_powrails.out
@@ -9,6 +9,7 @@
timestamp_ms: 6
energy_uws: 50
}
+ avg_used_power_mw: 38
}
power_rails{
name: "power.PR_2_uws"
@@ -20,6 +21,7 @@
timestamp_ms: 6
energy_uws: 70
}
+ avg_used_power_mw: 60
}
power_rails{
name: "power.PR_3_uws"
@@ -31,5 +33,6 @@
timestamp_ms: 6
energy_uws: 15
}
+ avg_used_power_mw: 7
}
}
\ No newline at end of file
diff --git a/test/trace_processor/tables/nulls.sql b/test/trace_processor/tables/nulls.sql
index 44e5132..cccbc47 100644
--- a/test/trace_processor/tables/nulls.sql
+++ b/test/trace_processor/tables/nulls.sql
@@ -37,6 +37,6 @@
(2, NULL, NULL, NULL, "test", NULL),
(1, "other", NULL, NULL, NULL, NULL),
(4, NULL, NULL, NULL, NULL, 1.0),
-(NULL, "test", 1.0, 1, NULL, NULL)
+(NULL, "test", 1.0, 1, NULL, NULL);
SELECT * from null_test;
diff --git a/test/trace_processor/tables/trace_metadata.json.out b/test/trace_processor/tables/trace_metadata.json.out
index 0d3f5d0..2a363cf 100644
--- a/test/trace_processor/tables/trace_metadata.json.out
+++ b/test/trace_processor/tables/trace_metadata.json.out
@@ -1,6 +1,7 @@
{
"trace_metadata": {
"trace_duration_ns": 9519159074,
+ "trace_uuid": "00000000-0000-0000-e77f-20a2204c2a49",
"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/track_event/experimental_slice_layout_depth.out b/test/trace_processor/track_event/experimental_slice_layout_depth.out
new file mode 100644
index 0000000..00f83ee
--- /dev/null
+++ b/test/trace_processor/track_event/experimental_slice_layout_depth.out
@@ -0,0 +1,4 @@
+"layout_depth"
+0
+0
+0
diff --git a/test/trace_processor/track_event/experimental_slice_layout_depth.py b/test/trace_processor/track_event/experimental_slice_layout_depth.py
new file mode 100644
index 0000000..3baf368
--- /dev/null
+++ b/test/trace_processor/track_event/experimental_slice_layout_depth.py
@@ -0,0 +1,43 @@
+#!/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 layout depth of async slices starting and
+# ending at the same time (see b/189222451).
+
+from os import sys
+
+import synth_common
+
+from synth_common import ms_to_ns
+trace = synth_common.create_trace()
+
+track1 = 1234
+track2 = 1235
+track3 = 1236
+
+trace.add_track_descriptor(track1)
+trace.add_track_descriptor(track2)
+trace.add_track_descriptor(track3)
+
+trace.add_track_event_slice(
+ "AsyncSlice", ts=ms_to_ns(0), dur=ms_to_ns(10), track=track1)
+
+trace.add_track_event_slice(
+ "AsyncSlice", ts=ms_to_ns(10), dur=ms_to_ns(10), track=track2)
+
+trace.add_track_event_slice(
+ "AsyncSlice", ts=ms_to_ns(20), dur=ms_to_ns(10), track=track3)
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/track_event/experimental_slice_layout_depth.sql b/test/trace_processor/track_event/experimental_slice_layout_depth.sql
new file mode 100644
index 0000000..b13dbe6
--- /dev/null
+++ b/test/trace_processor/track_event/experimental_slice_layout_depth.sql
@@ -0,0 +1,14 @@
+-- Licensed under the Apache License, Version 2.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 layout_depth from experimental_slice_layout
+where filter_track_ids = (select group_concat(track_id, ',') from slice);
\ No newline at end of file
diff --git a/test/trace_processor/track_event/index b/test/trace_processor/track_event/index
index d0881e0..d45510c 100644
--- a/test/trace_processor/track_event/index
+++ b/test/trace_processor/track_event/index
@@ -38,3 +38,9 @@
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
+
+# Async slices starting and ending at the same time
+experimental_slice_layout_depth.py experimental_slice_layout_depth.sql experimental_slice_layout_depth.out
+
+# Descriptor merging regression test (bug: b/197203390)
+../../data/trace_with_descriptor.pftrace merging_regression.sql merging_regression.out
diff --git a/test/trace_processor/track_event/merging_regression.out b/test/trace_processor/track_event/merging_regression.out
new file mode 100644
index 0000000..5158c9d
--- /dev/null
+++ b/test/trace_processor/track_event/merging_regression.out
@@ -0,0 +1,11 @@
+"ts"
+605361018360000
+605361018360000
+605361028265000
+605361028265000
+605361028361000
+605361028878000
+605361033445000
+605361033445000
+605361034257000
+605361035040000
diff --git a/test/trace_processor/track_event/merging_regression.sql b/test/trace_processor/track_event/merging_regression.sql
new file mode 100644
index 0000000..270e269
--- /dev/null
+++ b/test/trace_processor/track_event/merging_regression.sql
@@ -0,0 +1,19 @@
+--
+-- 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.
+--
+
+-- Actual query in this file does not matter: we only want to ensure that
+-- parsing of the trace succeeds.
+select ts from slice order by ts limit 10;
diff --git a/tools/BUILD.gn b/tools/BUILD.gn
index 772f6a2..37584e8 100644
--- a/tools/BUILD.gn
+++ b/tools/BUILD.gn
@@ -25,6 +25,7 @@
"compact_reencode",
"ftrace_proto_gen",
"proto_filter",
+ "proto_merger",
"protoprofile",
]
if (is_linux || is_android) {
diff --git a/tools/add_test_trace.sh b/tools/add_test_data
similarity index 83%
rename from tools/add_test_trace.sh
rename to tools/add_test_data
index 1eea759..a3f5b6b 100755
--- a/tools/add_test_trace.sh
+++ b/tools/add_test_data
@@ -13,8 +13,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# Adds a file or directory to /test/data/, uploads a new test_data.zip to GCS
+# and updates the sha1 in tools/install-build-deps.
+
set -e
+ROOT_DIR="$(dirname $(cd -P ${BASH_SOURCE[0]%/*}; pwd))"
+
echo ""
echo "Downloading latest copy of test data"
echo ""
@@ -28,9 +33,18 @@
unzip /tmp/latest-test-data.zip -d /tmp/latest-test-data
echo ""
-echo "Copying trace to temp folder"
+echo "Copying $1 to temp folder"
echo ""
-cp $1 /tmp/latest-test-data
+
+set -x
+if [ -d "$1" ]; then
+ DIR_NAME="$(basename $1)"
+ rm -rf "/tmp/latest-test-data/$DIR_NAME"
+ cp -r "$1" "/tmp/latest-test-data/$DIR_NAME"
+else
+ cp "$1" /tmp/latest-test-data
+fi
+set +x
echo ""
echo "Zipping file back up"
diff --git a/tools/add_tp_diff_test.py b/tools/add_tp_diff_test.py
index 83ce9d0..ce3ece7 100755
--- a/tools/add_tp_diff_test.py
+++ b/tools/add_tp_diff_test.py
@@ -13,7 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import argparse
import os
import pathlib
import sys
@@ -84,7 +83,7 @@
trace_file = ''
if trace_type == 'proto':
print('Proto traces should be added to the test-data zip '
- 'using the tools/add_test_trace.sh')
+ 'using the tools/add_test_data')
stdout_write('Provide the name of the trace (including any '
'extension) relative to test/data: ')
diff --git a/tools/busy_threads/busy_threads.cc b/tools/busy_threads/busy_threads.cc
index 56a80e2..3a58b50 100644
--- a/tools/busy_threads/busy_threads.cc
+++ b/tools/busy_threads/busy_threads.cc
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include <inttypes.h>
#include <stdint.h>
#include <unistd.h>
+#include <cinttypes>
#include <thread>
#include "perfetto/base/logging.h"
diff --git a/tools/cpu_utilization/cpu_utilization.cc b/tools/cpu_utilization/cpu_utilization.cc
index 2aea7ba..63d2618 100644
--- a/tools/cpu_utilization/cpu_utilization.cc
+++ b/tools/cpu_utilization/cpu_utilization.cc
@@ -15,13 +15,13 @@
*/
#include <fcntl.h>
-#include <inttypes.h>
#include <stdint.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
+#include <cinttypes>
#include <string>
#include "perfetto/base/logging.h"
diff --git a/tools/export_power_profiles.py b/tools/export_power_profiles.py
index db6e7ce..cea30f8 100755
--- a/tools/export_power_profiles.py
+++ b/tools/export_power_profiles.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env vpython
+#!/usr/bin/env python3
# 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.
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index cc8094b..53dfbc0 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -147,12 +147,6 @@
# Compiler defines which are passed through to the blueprint.
define_allowlist = r'^(GOOGLE_PROTO.*)|(ZLIB_.*)|(USE_MMAP)|(HAVE_HIDDEN)$'
-# Shared libraries which are not in PDK.
-library_not_in_pdk = {
- 'libandroid',
- 'libservices',
-}
-
# The directory where the generated perfetto_build_flags.h will be copied into.
buildflags_dir = 'include/perfetto/base/build_configs/android_tree'
@@ -210,6 +204,7 @@
('include_dirs', {'bionic/libc/kernel'}),
],
'perfetto_integrationtests': [
+ ('cflags', {'-fno-finite-loops'}),
('test_suites', {'general-tests'}),
('test_config', 'PerfettoIntegrationTests.xml'),
],
@@ -288,6 +283,7 @@
module.static_libs.add('libbase')
module.static_libs.add('liblzma')
module.static_libs.add('libdexfile_support')
+ module.runtime_libs.add('libdexfile') # libdexfile_support dependency
def enable_libunwind(module):
@@ -388,13 +384,13 @@
if isinstance(value, set):
value = sorted(value)
if isinstance(value, list):
- output.append(' %s: [' % name)
+ output.append(' %s: [' % name)
for item in sorted(value) if sort else value:
- output.append(' "%s",' % item)
- output.append(' ],')
+ output.append(' "%s",' % item)
+ output.append(' ],')
return
if isinstance(value, bool):
- output.append(' %s: true,' % name)
+ output.append(' %s: true,' % name)
return
if isinstance(value, Target):
value.to_string(output)
@@ -404,12 +400,12 @@
for k, v in value.items():
write_blueprint_key_value(kv_output, k, v)
- output.append(' %s: {' % name)
+ output.append(' %s: {' % name)
for line in kv_output:
- output.append(' %s' % line)
- output.append(' },')
+ output.append(' %s' % line)
+ output.append(' },')
return
- output.append(' %s: "%s",' % (name, value))
+ output.append(' %s: "%s",' % (name, value))
class Target(object):
@@ -436,10 +432,10 @@
self._output_field(nested_out, 'strip')
if nested_out:
- output.append(' %s: {' % self.name)
+ output.append(' %s: {' % self.name)
for line in nested_out:
- output.append(' %s' % line)
- output.append(' },')
+ output.append(' %s' % line)
+ output.append(' },')
def _output_field(self, output, name, sort=True):
value = getattr(self, name)
@@ -458,6 +454,7 @@
self.shared_libs = set()
self.static_libs = set()
self.whole_static_libs = set()
+ self.runtime_libs = set()
self.tools = set()
self.cmd = None
self.host_supported = False
@@ -501,6 +498,7 @@
self._output_field(output, 'shared_libs')
self._output_field(output, 'static_libs')
self._output_field(output, 'whole_static_libs')
+ self._output_field(output, 'runtime_libs')
self._output_field(output, 'tools')
self._output_field(output, 'cmd', sort=False)
self._output_field(output, 'host_supported')
@@ -530,32 +528,26 @@
self._output_field(target_out, 'android')
self._output_field(target_out, 'host')
if target_out:
- output.append(' target: {')
+ output.append(' target: {')
for line in target_out:
- output.append(' %s' % line)
- output.append(' },')
-
- disable_pdk = any(name in library_not_in_pdk for name in self.shared_libs)
- if self.user_debug_flag or disable_pdk:
- output.append(' product_variables: {')
- if disable_pdk:
- output.append(' pdk: {')
- output.append(' enabled: false,')
- output.append(' },')
- if self.user_debug_flag:
- output.append(' debuggable: {')
- output.append(
- ' cflags: ["-DPERFETTO_BUILD_WITH_ANDROID_USERDEBUG"],')
- output.append(' },')
- output.append(' },')
- if self.lto is not None:
- output.append(' target: {')
- output.append(' android: {')
- output.append(' lto: {')
- output.append(' thin: %s,' % 'true' if self.lto else 'false')
- output.append(' },')
+ output.append(' %s' % line)
output.append(' },')
- output.append(' },')
+
+ if self.user_debug_flag:
+ output.append(' product_variables: {')
+ output.append(' debuggable: {')
+ output.append(
+ ' cflags: ["-DPERFETTO_BUILD_WITH_ANDROID_USERDEBUG"],')
+ output.append(' },')
+ output.append(' },')
+ if self.lto is not None:
+ output.append(' target: {')
+ output.append(' android: {')
+ output.append(' lto: {')
+ output.append(' thin: %s,' % 'true' if self.lto else 'false')
+ output.append(' },')
+ output.append(' },')
+ output.append(' },')
output.append('}')
output.append('')
diff --git a/tools/gen_bazel b/tools/gen_bazel
index a8b7309..9257d75 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -45,6 +45,7 @@
'target_os="linux"',
'enable_perfetto_heapprofd=false',
'enable_perfetto_traced_perf=false',
+ 'perfetto_force_dcheck="off"',
])
# Default targets to translate to the blueprint file.
@@ -70,6 +71,8 @@
'//src/protozero:protozero',
'//src/protozero/protoc_plugin:protozero_plugin',
'//src/protozero/protoc_plugin:cppgen_plugin',
+ '//tools/proto_filter:proto_filter',
+ '//tools/proto_merger:proto_merger',
] + public_targets
# Root proto targets (to force discovery of intermediate proto targets).
@@ -82,6 +85,7 @@
'//protos/perfetto/metrics/android:lite',
'//protos/perfetto/trace:lite',
'//protos/perfetto/config:lite',
+ '//protos/third_party/chromium:lite',
]
# Path for the protobuf sources in the standalone build.
diff --git a/tools/gen_ui_imports b/tools/gen_ui_imports
new file mode 100755
index 0000000..1f10a38
--- /dev/null
+++ b/tools/gen_ui_imports
@@ -0,0 +1,77 @@
+#!/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.
+
+"""Generates TypeScript files that import all subdirectories.
+This is useful for plugins/extensions. If you have two modules:
+- core/
+- plugins/myplugin/
+In general you would like the dependency to only go one way:
+- plugins/myplugin/ -> core/
+But you still need some index file to import all plugins for the sake of
+bundling. This avoids having to manually edit core/ for every
+plugin you add.
+"""
+
+from __future__ import print_function
+
+import os
+import argparse
+import subprocess
+import sys
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+UI_SRC_DIR = os.path.join(ROOT_DIR, 'ui', 'src')
+
+def gen_imports(input_dir, output_path):
+ paths = [os.path.join(input_dir, p) for p in os.listdir(input_dir)]
+ paths = [p for p in paths if os.path.isdir(p)]
+ paths.sort()
+
+ lines = []
+ for path in paths:
+ rel_path = os.path.relpath(path, os.path.dirname(output_path))
+ lines.append(f"import '{rel_path}';")
+ expected = '\n'.join(lines)
+
+ with open(output_path, 'w') as f:
+ f.write(expected)
+ return True
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__,
+ formatter_class=argparse.RawDescriptionHelpFormatter)
+ parser.add_argument('INPUT')
+ parser.add_argument('--out', required=True)
+ args = parser.parse_args()
+ input_dir = args.INPUT
+ output_path = args.out
+
+ if not os.path.isdir(input_dir):
+ print(f'INPUT argument {input_dir} must be a directory')
+ exit(1)
+
+ output_dir = os.path.dirname(output_path)
+ if output_dir and not os.path.isdir(output_dir):
+ print(f'--out ({output_path}) parent directory ({output_dir}) must exist')
+ exit(1)
+ if os.path.isdir(output_path):
+ print(f'--out ({output_path}) should not be a directory')
+ exit(1)
+
+ success = gen_imports(input_dir, output_path)
+ return 0 if success else 1
+
+if __name__ == '__main__':
+ exit(main())
diff --git a/tools/get_perfetto_prebuilt.py b/tools/get_perfetto_prebuilt.py
new file mode 100644
index 0000000..99f3459
--- /dev/null
+++ b/tools/get_perfetto_prebuilt.py
@@ -0,0 +1,122 @@
+# 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 source defines a self-contained function to fetch a perfetto prebuilt.
+
+This function is copy/pasted by //tools/roll-prebuilts in different places:
+- Into the //tools/{trace_processor, traceconv} scripts, which are just plain
+ wrappers around executables.
+- Into the //tools/{heap_profiler, record_android_trace} scripts, which contain
+ some other hand-written python code.
+In both cases toll-prebuilts copies this source (together with a manifest) into
+a section annotated with "BEGIN_SECTION_GENERATED_BY(roll-prebuilts)" / END... .
+The automated-copy-paste is to keep those script hermetic, so people can just
+download and run them without checking out the repo.
+
+The manifest argument looks as follows in the generated files:
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool': 'trace_to_text',
+ 'arch': 'mac-amd64',
+ 'file_name': 'trace_to_text',
+ 'file_size': 7087080,
+ 'url': https://commondatastorage.googleapis.com/.../trace_to_text',
+ 'sha256': 7d957c005b0dc130f5bd855d6cec27e060d38841b320d04840afc569f9087490',
+ 'platform': 'darwin',
+ 'machine': 'x86_64'
+ },
+ ...
+]
+
+The intended usage is:
+
+bin_path = get_perfetto_prebuilt('trace_processor_shell')
+subprocess.call(bin_path, ...)
+"""
+
+from logging import exception
+
+PERFETTO_PREBUILT_MANIFEST = []
+
+# COPIED_SECTION_START_MARKER
+
+
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ print('Downloading ' + url)
+ subprocess.check_call(['curl', '-f', '-L', '-#', '-o', tmp_path, url])
+ with open(tmp_path, 'rb') as fd:
+ actual_sha256 = hashlib.sha256(fd.read()).hexdigest()
+ if actual_sha256 != sha256:
+ raise Exception('Checksum mismatch for %s (actual: %s, expected: %s)' %
+ (url, actual_sha256, sha256))
+ os.chmod(tmp_path, 0o755)
+ os.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and entry.get(
+ 'platform') == plat and machine in entry.get('machine', []):
+ manifest_entry = entry
+ break
+ if manifest_entry is None:
+ if soft_fail:
+ return None
+ raise Exception(
+ ('No prebuilts available for %s-%s\n' % (plat, machine)) +
+ 'See https://perfetto.dev/docs/contributing/build-instructions')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
diff --git a/tools/heap_profile b/tools/heap_profile
index f3ee35a..387d767 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -29,15 +29,6 @@
import tempfile
import time
import uuid
-import platform
-
-
-TRACE_TO_TEXT_SHAS = {
- 'linux': '7e3e10dfb324e31723efd63ac25037856e06eba0',
- 'mac': '21f0f42dd019b4f09addd404a114fbf2322ca8a4',
-}
-TRACE_TO_TEXT_PATH = tempfile.gettempdir()
-TRACE_TO_TEXT_BASE_URL = ('https://storage.googleapis.com/perfetto/')
NULL = open(os.devnull)
NOOUT = {
@@ -47,37 +38,6 @@
UUID = str(uuid.uuid4())[-6:]
-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
-
-
-def load_trace_to_text(os_name):
- sha_value = TRACE_TO_TEXT_SHAS[os_name]
- file_name = 'trace_to_text-' + os_name + '-' + sha_value
- local_file = os.path.join(TRACE_TO_TEXT_PATH, file_name)
-
- if os.path.exists(local_file):
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- else:
- return local_file
-
- url = TRACE_TO_TEXT_BASE_URL + file_name
- subprocess.check_call(['curl', '-L', '-#', '-o', local_file, url])
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- raise ValueError("Invalid signature.")
- os.chmod(local_file, 0o755)
- return local_file
-
-
PACKAGES_LIST_CFG = '''data_sources {
config {
name: "android.packages_list"
@@ -120,6 +80,7 @@
IS_INTERRUPTED = False
+
def sigint_handler(sig, frame):
global IS_INTERRUPTED
IS_INTERRUPTED = True
@@ -128,44 +89,52 @@
def print_no_profile_error():
print("No profiles generated", file=sys.stderr)
print(
- "If this is unexpected, check "
- "https://perfetto.dev/docs/data-sources/native-heap-profiler#troubleshooting.",
- file=sys.stderr)
+ "If this is unexpected, check "
+ "https://perfetto.dev/docs/data-sources/native-heap-profiler#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),
+ '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()
+ ['adb', 'shell', 'getprop',
+ 'ro.build.version.release_or_codename']).decode('utf-8').strip()
return KNOWN_ISSUES.get(release_or_codename, None)
+
SDK = {
'R': 30,
}
+
def release_or_newer(release):
- sdk = int(subprocess.check_output(
- ['adb', 'shell', 'getprop', 'ro.system.build.version.sdk']
- ).decode('utf-8').strip())
+ sdk = int(
+ subprocess.check_output(
+ ['adb', 'shell', 'getprop',
+ 'ro.system.build.version.sdk']).decode('utf-8').strip())
if sdk >= SDK[release]:
return True
codename = subprocess.check_output(
- ['adb', 'shell', 'getprop', 'ro.build.version.codename']
- ).decode('utf-8').strip()
+ ['adb', 'shell', 'getprop',
+ 'ro.build.version.codename']).decode('utf-8').strip()
return codename == release
+
ORDER = ['-n', '-p', '-i', '-o']
+
def arg_order(action):
result = len(ORDER)
for opt in action.option_strings:
@@ -173,16 +142,18 @@
result = min(ORDER.index(opt), result)
return result, action.option_strings[0].strip('-')
+
def print_options(parser):
for action in sorted(parser._actions, key=arg_order):
if action.help is argparse.SUPPRESS:
continue
opts = ', '.join('`' + x + '`' for x in action.option_strings)
- metavar = '' if action.metavar is None else ' _' + action.metavar + '_'
+ metavar = '' if action.metavar is None else ' _' + action.metavar + '_'
print('{}{}'.format(opts, metavar))
print(': {}'.format(action.help))
print()
+
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument(
@@ -229,14 +200,12 @@
parser.add_argument(
"--all-heaps",
action="store_true",
- help="Collect allocations from all heaps registered by target."
- )
+ 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."
- )
+ "Android tree.")
parser.add_argument(
"--disable-selinux",
action="store_true",
@@ -314,10 +283,7 @@
metavar="DIRECTORY",
default=None)
parser.add_argument(
- "--print-options",
- action="store_true",
- help=argparse.SUPPRESS
- )
+ "--print-options", action="store_true", help=argparse.SUPPRESS)
args = parser.parse_args()
if args.print_options:
@@ -352,8 +318,8 @@
target_cfg += CFG_INDENT + "block_client: true\n"
if args.block_client_timeout:
target_cfg += (
- CFG_INDENT + "block_client_timeout_us: %s\n" % args.block_client_timeout
- )
+ CFG_INDENT +
+ "block_client_timeout_us: %s\n" % args.block_client_timeout)
if args.no_startup:
target_cfg += CFG_INDENT + "no_startup: true\n"
if args.no_running:
@@ -401,25 +367,9 @@
# 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)
+ trace_to_text_binary = get_perfetto_prebuilt(
+ 'trace_to_text', soft_fail=True)
known_issues = maybe_known_issues()
if known_issues:
@@ -432,8 +382,8 @@
if uuid_trace:
profile_device_path = '/data/misc/perfetto-traces/profile-' + UUID
else:
- user = subprocess.check_output(
- ['adb', 'shell', 'whoami']).decode('utf-8').strip()
+ 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}} | '
@@ -461,18 +411,17 @@
os.mkdir(profile_target)
if not os.path.isdir(profile_target):
- print("Output directory {} not found".format(profile_target),
- file=sys.stderr)
+ print(
+ "Output directory {} not found".format(profile_target), file=sys.stderr)
return 1
if os.listdir(profile_target):
- print("Output directory {} not empty".format(profile_target),
- file=sys.stderr)
+ print(
+ "Output directory {} not empty".format(profile_target), file=sys.stderr)
return 1
perfetto_pid = subprocess.check_output(
- ['adb', 'exec-out',
- perfetto_cmd.format(cfg=cfg)]).strip()
+ ['adb', 'exec-out', perfetto_cmd.format(cfg=cfg)]).strip()
try:
perfetto_pid = int(perfetto_pid.strip())
except ValueError:
@@ -503,8 +452,8 @@
time.sleep(1)
subprocess.check_call(
['adb', 'pull', '/data/local/tmp/heapprofd_profile', profile_target])
- print(
- "Pulled simpleperf profile to " + profile_target + "/heapprofd_profile")
+ print("Pulled simpleperf profile to " + profile_target +
+ "/heapprofd_profile")
# Wait for perfetto cmd to return.
while exists:
@@ -513,15 +462,17 @@
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, profile_host_path],
+ stdout=NULL)
if uuid_trace:
- subprocess.check_call(
- ['adb', 'shell', 'rm', profile_device_path], stdout=NULL)
+ subprocess.check_call(['adb', 'shell', 'rm', profile_device_path],
+ stdout=NULL)
- if not has_trace_to_text:
+ if trace_to_text_binary is None:
print('Wrote profile to {}'.format(profile_host_path))
- print('This file can be opened using the Perfetto UI, https://ui.perfetto.dev')
+ print(
+ 'This file can be opened using the Perfetto UI, https://ui.perfetto.dev'
+ )
return 0
binary_path = os.getenv('PERFETTO_BINARY_PATH')
@@ -544,29 +495,32 @@
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)
+ 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)
+ 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)
+ 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'))
+ concat_files.append(os.path.join(profile_target, 'deobfuscation-packets'))
else:
- print("Failed to deobfuscate. Continuing without deobfuscated.",
- file=sys.stderr)
+ 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:
@@ -597,27 +551,155 @@
for profile_file in profile_files:
shutil.copy(os.path.join(profile_path, profile_file), profile_target)
- subprocess.check_call(
- ['gzip'] +
- [os.path.join(profile_target, x) for x in profile_files])
-
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)
+ if not sys.platform.startswith('win'):
+ subprocess.check_call(
+ ['gzip'] + [os.path.join(profile_target, x) for x in profile_files])
+ 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)
if symlink_path is not None:
- print("Wrote profiles to {} (symlink {})".format(
- profile_target, symlink_path))
+ print("Wrote profiles to {} (symlink {})".format(profile_target,
+ symlink_path))
else:
print("Wrote profiles to {}".format(profile_target))
- print("These can be viewed using pprof. Googlers: head to pprof/ and "
- "upload them.")
+ print("The raw-trace file can be viewed using https://ui.perfetto.dev.")
+ print("The heap_dump.* files can be viewed using pprof/ (Googlers only) " +
+ "or https://www.speedscope.app/.")
+ print("The two above are equivalent. The raw-trace contains the union of " +
+ "all the heap dumps.")
+# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
+# Revision: 387c10f55b96e95f96ec9248c3af28772bccfff0
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'mac-amd64',
+ 'file_name':
+ 'trace_to_text',
+ 'file_size':
+ 7087080,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/mac-amd64/trace_to_text',
+ 'sha256':
+ '19126f67c1edd3e525c63d3cc5085ea965d77868b91d163052f8f608cf496cd8',
+ 'platform':
+ 'darwin',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'windows-amd64',
+ 'file_name':
+ 'trace_to_text.exe',
+ 'file_size':
+ 6703616,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/windows-amd64/trace_to_text.exe',
+ 'sha256':
+ 'fc776c807682c1de0785468190fe9795fda97f2a9c32dad15affe24b81dad817',
+ 'platform':
+ 'win32',
+ 'machine': ['amd64']
+}, {
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'linux-amd64',
+ 'file_name':
+ 'trace_to_text',
+ 'file_size':
+ 7437720,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/linux-amd64/trace_to_text',
+ 'sha256':
+ '8112656e058a8ebbd6f7251452527c51c0a3e88bc160a33d95e3da61228d1285',
+ 'platform':
+ 'linux',
+ 'machine': ['x86_64']
+}]
+
+
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ print('Downloading ' + url)
+ subprocess.check_call(['curl', '-f', '-L', '-#', '-o', tmp_path, url])
+ with open(tmp_path, 'rb') as fd:
+ actual_sha256 = hashlib.sha256(fd.read()).hexdigest()
+ if actual_sha256 != sha256:
+ raise Exception('Checksum mismatch for %s (actual: %s, expected: %s)' %
+ (url, actual_sha256, sha256))
+ os.chmod(tmp_path, 0o755)
+ os.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and entry.get(
+ 'platform') == plat and machine in entry.get('machine', []):
+ manifest_entry = entry
+ break
+ if manifest_entry is None:
+ if soft_fail:
+ return None
+ raise Exception(
+ ('No prebuilts available for %s-%s\n' % (plat, machine)) +
+ 'See https://perfetto.dev/docs/contributing/build-instructions')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
+
+
+# END_SECTION_GENERATED_BY(roll-prebuilts)
+
if __name__ == '__main__':
sys.exit(main(sys.argv))
diff --git a/tools/idle_alloc.cc b/tools/idle_alloc.cc
index 1a1dd5a..5224884 100644
--- a/tools/idle_alloc.cc
+++ b/tools/idle_alloc.cc
@@ -14,11 +14,8 @@
* limitations under the License.
*/
-#include <memory>
-
#include <errno.h>
#include <fcntl.h>
-#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -27,6 +24,9 @@
#include <sys/types.h>
#include <unistd.h>
+#include <cinttypes>
+#include <memory>
+
namespace {
constexpr auto kIdleSize = 10000 * 4096;
diff --git a/tools/install-build-deps b/tools/install-build-deps
index 6575bea..e1e90d8 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -28,7 +28,7 @@
from platform import system, machine
# The format for the deps below is the following:
-# (target_folder, source_url, sha1, target_platform)
+# (target_folder, source_url, sha1, target_os, target_arch)
# |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.
@@ -121,13 +121,13 @@
# 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',
+ 'https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/clang-llvmorg-14-init-3191-g0e03450a-1.tgz',
+ 'dd7479d43ce61401e057a5dee8b7e32bc2bd0d0e15d4f46c6858daf9170c9978',
'linux', 'x64'),
Dependency(
'buildtools/win/clang.tgz',
- 'https://commondatastorage.googleapis.com/chromium-browser-clang/Win/clang-llvmorg-12-init-5035-gd0abc757-3.tgz',
- 'b2854d871a466e3a060469b5edb24ca355ef64576d38778f64acbd3c6d7cf530',
+ 'https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/clang-llvmorg-14-init-3191-g0e03450a-1.tgz',
+ 'dd7479d43ce61401e057a5dee8b7e32bc2bd0d0e15d4f46c6858daf9170c9978',
'windows', 'x64'),
]
@@ -234,8 +234,8 @@
# Example traces for regression tests.
Dependency(
'test/data.zip',
- 'https://storage.googleapis.com/perfetto/test-data-20210518-223638.zip',
- 'a9119ae4828fae92c9ec8449e3fd91d753e60b60fa59611fb8e6c0dd6ed69b13',
+ 'https://storage.googleapis.com/perfetto/test-data-20210909-141933.zip',
+ '95597358b8d434338815731948cf2bb96e2015b8595f05c37c053c2e11f11408',
'all', 'all',
),
@@ -243,6 +243,11 @@
Dependency('buildtools/linenoise',
'https://fuchsia.googlesource.com/third_party/linenoise.git',
'c894b9e59f02203dbe4e2be657572cf88c4230c3', 'all', 'all'),
+
+ # Bloaty, used to investigate binary size
+ Dependency('buildtools/bloaty.zip',
+ 'https://storage.googleapis.com/perfetto/bloaty-1.1-b3b829de35babc2fe831b9488ad2e50bca939412-mac.zip',
+ '2d301bd72a20e3f42888c9274ceb4dca76c103608053572322412c2c65ab8cb8', 'darwin', 'x64'),
]
# Dependencies required to build Android code.
@@ -327,6 +332,24 @@
TYPEFACES_SHA256, TYPEFACES_SHA256, 'all', 'all')
]
+# Sysroots required to cross-compile Linux targets (linux-arm{,64}).
+# These are taken from Chromium's build/linux/sysroot_scripts/sysroots.json.
+BUILD_DEPS_LINUX_CROSS_SYSROOTS = [
+ Dependency(
+ 'buildtools/debian_sid_arm-sysroot.tgz',
+ 'https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain/11d6f690ca49e8ba01a1d8c5346cedad2cf308fd/debian_sid_arm_sysroot.tar.xz',
+ 'ff192fe073d140d836c9ca1e68f7200d558bb9aa6c5c8f4f76f794f82890f99a',
+ 'linux', 'all'),
+ Dependency(
+ 'buildtools/debian_sid_arm64-sysroot.tgz',
+ 'https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain/2befe8ce3e88be6080e4fb7e6d412278ea6a7625/debian_sid_arm64_sysroot.tar.xz',
+ 'e4389eab2fe363f3fbdfa4d3ce9d94457d78fd2c0e62171a7534867623eadc90',
+ 'linux', 'all'),
+]
+
+ALL_DEPS = (BUILD_DEPS_HOST + BUILD_DEPS_ANDROID +
+ BUILD_DEPS_LINUX_CROSS_SYSROOTS + TEST_DEPS_ANDROID + UI_DEPS)
+
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')
@@ -428,9 +451,9 @@
logging.info('Clearing %s', node_modules)
subprocess.check_call(['git', 'clean', '-qxffd', node_modules],
cwd=ROOT_DIR)
- 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)
+ logging.info("Running `npm ci` in {0}".format(UI_DIR))
+ # `npm ci` is like `npm install` but respects package-lock.json.
+ subprocess.check_call([os.path.join(TOOLS_DIR, 'npm'), 'ci'], 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')
@@ -455,26 +478,29 @@
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'):
- continue
- logging.info('Downloading %s from %s', dep.target_platform,
- dep.source_url)
- with tempfile.NamedTemporaryFile(delete=False) as f:
- f.close()
- DownloadURL(dep.source_url, f.name)
- actual_checksum = 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))
+ for dep in ALL_DEPS:
+ if dep.source_url.endswith('.git'):
+ continue
+ logging.info('Downloading %s for %s-%s', dep.source_url,
+ dep.target_os, dep.target_arch)
+ with tempfile.NamedTemporaryFile(delete=False) as f:
+ f.close()
+ DownloadURL(dep.source_url, f.name)
+ actual_checksum = 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))
def Main():
parser = argparse.ArgumentParser()
- parser.add_argument('--android', action='store_true')
- parser.add_argument('--ui', action='store_true')
+ parser.add_argument('--android', action='store_true',
+ help='NDK and emulator images target_os="android"')
+ parser.add_argument('--linux-arm', action='store_true',
+ help='Debian sysroots for target_os="linux" target_cpu="arm|arm64"')
+ parser.add_argument('--ui', action='store_true',
+ help='Node and NPM packages to Build the Web-based UI via ./ui/build')
parser.add_argument('--check-only')
parser.add_argument('--filter', default='')
parser.add_argument('--verify', help='Check all URLs', action='store_true')
@@ -484,11 +510,19 @@
if args.verify:
CheckHashes()
return 0
+
+ target_os = system().lower()
+ if args.ui and target_os == 'windows':
+ print('Building the UI on Windows is unsupported')
+ return 1
+
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.linux_arm:
+ deps += BUILD_DEPS_LINUX_CROSS_SYSROOTS
if args.ui:
deps += UI_DEPS
deps_updated = False
@@ -498,7 +532,6 @@
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
diff --git a/tools/java_heap_dump b/tools/java_heap_dump
index 5f301b6..a0e69220 100755
--- a/tools/java_heap_dump
+++ b/tools/java_heap_dump
@@ -173,8 +173,6 @@
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
diff --git a/tools/multithreaded_alloc.cc b/tools/multithreaded_alloc.cc
index 6125777..4c5e603 100644
--- a/tools/multithreaded_alloc.cc
+++ b/tools/multithreaded_alloc.cc
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <atomic>
+#include <cinttypes>
#include <condition_variable>
#include <iterator>
#include <mutex>
diff --git a/tools/open_trace_in_ui b/tools/open_trace_in_ui
new file mode 100755
index 0000000..c2360bb
--- /dev/null
+++ b/tools/open_trace_in_ui
@@ -0,0 +1,92 @@
+#!/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
+import http.server
+import os
+import socketserver
+import sys
+import webbrowser
+
+
+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 prt(msg, colors=ANSI.END):
+ print(colors + msg + ANSI.END)
+
+
+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 main():
+ examples = '\n'.join([
+ ANSI.BOLD + 'Usage:' + ANSI.END, ' -i path/trace_file_name'
+ ])
+ parser = argparse.ArgumentParser(
+ epilog=examples, formatter_class=argparse.RawTextHelpFormatter)
+
+ help = 'Input trace filename'
+ parser.add_argument('-i', '--trace', help=help)
+
+ args = parser.parse_args()
+ trace_file = args.trace
+
+ if trace_file is None:
+ prt('Please specify trace file name with -i/--trace argument', ANSI.RED)
+ sys.exit(1)
+ elif not os.path.exists(trace_file):
+ prt('%s not found ' % trace_file, ANSI.RED)
+ sys.exit(1)
+
+ prt('Opening the trace (%s) in the browser' % trace_file)
+ open_trace_in_browser(trace_file)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/tools/proto_merger/BUILD.gn b/tools/proto_merger/BUILD.gn
new file mode 100644
index 0000000..533d8aa
--- /dev/null
+++ b/tools/proto_merger/BUILD.gn
@@ -0,0 +1,35 @@
+# 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_merger") {
+ testonly = true
+ deps = [
+ "../../gn:default_deps",
+ "../../gn:protobuf_full",
+ "../../src/base",
+ ]
+ sources = [
+ "allowlist.cc",
+ "allowlist.h",
+ "main.cc",
+ "proto_file.cc",
+ "proto_file.h",
+ "proto_file_serializer.cc",
+ "proto_file_serializer.h",
+ "proto_merger.cc",
+ "proto_merger.h",
+ ]
+}
diff --git a/tools/proto_merger/allowlist.cc b/tools/proto_merger/allowlist.cc
new file mode 100644
index 0000000..2a1c859
--- /dev/null
+++ b/tools/proto_merger/allowlist.cc
@@ -0,0 +1,130 @@
+/*
+ * 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 appicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/proto_merger/allowlist.h"
+
+#include <google/protobuf/descriptor.pb.h>
+
+#include "perfetto/ext/base/string_utils.h"
+
+namespace perfetto {
+namespace proto_merger {
+namespace {
+
+std::vector<std::string> SplitFieldPath(const std::string& name) {
+ if (name.empty())
+ return {};
+
+ if (name[0] == '.')
+ return base::SplitString(name.substr(1), ".");
+
+ return base::SplitString(name, ".");
+}
+
+Allowlist::Message& ResolveMessageForDescriptor(
+ const google::protobuf::Descriptor& desc,
+ Allowlist& allowlist) {
+ if (!desc.containing_type())
+ return allowlist.messages[desc.name()];
+
+ Allowlist::Message& parent =
+ ResolveMessageForDescriptor(*desc.containing_type(), allowlist);
+ return parent.nested_messages[desc.name()];
+}
+
+void AllowlistEnum(const google::protobuf::EnumDescriptor& desc,
+ Allowlist& allowlist) {
+ if (!desc.containing_type()) {
+ allowlist.enums.emplace(desc.name());
+ return;
+ }
+
+ auto& containing =
+ ResolveMessageForDescriptor(*desc.containing_type(), allowlist);
+ containing.enums.emplace(desc.name());
+}
+
+void AllowlistField(const google::protobuf::FieldDescriptor& desc,
+ Allowlist& allowlist) {
+ auto& containing =
+ ResolveMessageForDescriptor(*desc.containing_type(), allowlist);
+
+ // Check if this field is already allowed and return if so; otherwise add it.
+ // We need to do slightly different things based on whether or not this field
+ // is in a oneof.
+ if (desc.containing_oneof()) {
+ auto& oneof = containing.oneofs[desc.containing_oneof()->name()];
+ if (!oneof.emplace(desc.number()).second) {
+ return;
+ }
+ } else {
+ if (!containing.fields.emplace(desc.number()).second)
+ return;
+ }
+
+ switch (desc.type()) {
+ case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
+ // For message types, we recursively allow all fields under it including
+ // any types those fields may depend on.
+ for (int i = 0; i < desc.message_type()->field_count(); ++i) {
+ AllowlistField(*desc.message_type()->field(i), allowlist);
+ }
+ break;
+ case google::protobuf::FieldDescriptor::TYPE_ENUM:
+ // For enums, we allow the enum type.
+ AllowlistEnum(*desc.enum_type(), allowlist);
+ break;
+ default:
+ // We don't need to do anything for primitive types.
+ break;
+ }
+}
+
+} // namespace
+
+base::Status AllowlistFromFieldList(
+ const google::protobuf::Descriptor& desc,
+ const std::vector<std::string>& allowed_fields,
+ Allowlist& allowlist) {
+ for (const auto& field_path : allowed_fields) {
+ std::vector<std::string> pieces = SplitFieldPath(field_path);
+ const auto* current = &desc;
+ for (size_t i = 0; i < pieces.size(); ++i) {
+ const auto* field = current->FindFieldByName(pieces[i]);
+ if (!field) {
+ return base::ErrStatus("Field %s in message %s not found.",
+ pieces[i].c_str(), current->name().c_str());
+ }
+ if (i == pieces.size() - 1) {
+ // For the last field, allow the field and any messages it depends on
+ // recursively.
+ AllowlistField(*field, allowlist);
+ break;
+ }
+
+ // All fields before the last should lead to a message type.
+ if (field->type() != google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
+ return base::ErrStatus("Field %s in message %s has a non-message type",
+ field->name().c_str(), desc.name().c_str());
+ }
+ current = field->message_type();
+ }
+ }
+ return base::OkStatus();
+}
+
+} // namespace proto_merger
+} // namespace perfetto
diff --git a/tools/proto_merger/allowlist.h b/tools/proto_merger/allowlist.h
new file mode 100644
index 0000000..64d70a5
--- /dev/null
+++ b/tools/proto_merger/allowlist.h
@@ -0,0 +1,60 @@
+/*
+ * 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 TOOLS_PROTO_MERGER_ALLOWLIST_H_
+#define TOOLS_PROTO_MERGER_ALLOWLIST_H_
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "perfetto/base/status.h"
+
+// We include this intentionally instead of forward declaring to allow
+// for an easy find/replace transformation when moving to Google3.
+#include <google/protobuf/descriptor.h>
+
+namespace perfetto {
+namespace proto_merger {
+
+// Represents an allow-list for proto messages, fields and enums.
+struct Allowlist {
+ using Oneof = std::set<int>;
+ struct Message {
+ std::set<std::string> enums;
+ std::map<std::string, Oneof> oneofs;
+ std::set<int> fields;
+
+ // Needs to be a std::map as std::unordered_map causes complaints about
+ // self-referentiality from GCC.
+ std::map<std::string, Message> nested_messages;
+ };
+ std::map<std::string, Message> messages;
+ std::set<std::string> enums;
+};
+
+// Creates a Allowlist struct from a list of allowed fields rooted at the given
+// descriptor.
+base::Status AllowlistFromFieldList(
+ const google::protobuf::Descriptor&,
+ const std::vector<std::string>& allowed_fields,
+ Allowlist& allowlist);
+
+} // namespace proto_merger
+} // namespace perfetto
+
+#endif // TOOLS_PROTO_MERGER_ALLOWLIST_H_
diff --git a/tools/proto_merger/main.cc b/tools/proto_merger/main.cc
new file mode 100644
index 0000000..3e4376c
--- /dev/null
+++ b/tools/proto_merger/main.cc
@@ -0,0 +1,282 @@
+/*
+ * 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 <stdio.h>
+#include <string>
+
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+#include "perfetto/base/logging.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_utils.h"
+#include "perfetto/ext/base/version.h"
+#include "tools/proto_merger/allowlist.h"
+#include "tools/proto_merger/proto_file.h"
+#include "tools/proto_merger/proto_file_serializer.h"
+#include "tools/proto_merger/proto_merger.h"
+
+namespace perfetto {
+namespace proto_merger {
+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());
+}
+
+struct ImportResult {
+ std::unique_ptr<google::protobuf::compiler::Importer> importer;
+ const google::protobuf::FileDescriptor* file_descriptor;
+};
+
+ImportResult ImportProto(const std::string& proto_file,
+ const std::string& proto_dir_path) {
+ MultiFileErrorCollectorImpl mfe;
+
+ google::protobuf::compiler::DiskSourceTree dst;
+ dst.MapPath("", proto_dir_path);
+
+ ImportResult result;
+ result.importer.reset(new google::protobuf::compiler::Importer(&dst, &mfe));
+ result.file_descriptor = result.importer->Import(proto_file);
+ return result;
+}
+
+const char kUsage[] =
+ R"(Usage: proto_merger [-i input proto] [-I import dir]
+
+-i, --input: Path to the input .proto file (relative to
+ --input-include directory). The contents of this
+ file will be updated using the upstream proto.
+-I, --input-include: Root directory from which includes for --input
+ proto should be searched.
+-u, --upstream: Path to the upstream .proto file; the contents of
+ this file will be used to update
+ the input proto.
+-U, --upstream-include: Root directory from which includes for --upstream
+ proto should be searched.
+-a, --allowlist: Allowlist file which is used to add new fields in
+ the upstream proto to the input proto.
+-r, --upstream-root-message: Root message in the upstream proto for which new
+ fields from the allowlist will be allowed.
+-o, --output: Output path for writing the merged proto file.
+
+Example usage:
+
+# Updating logs proto from Perfetto repo (must be run in G3):
+ proto_merger \
+ -u third_party/perfetto/protos/perfetto/trace/perfetto_trace.proto \
+ -U . \
+ -i <path to logs proto>/perfetto_log.proto \
+ -I . \
+ --allowlist /tmp/allowlist.txt \
+ -r perfetto.protos.Trace \
+ --output /tmp/output.proto
+)";
+
+int Main(int argc, char** argv) {
+ static const option long_options[] = {
+ {"help", no_argument, nullptr, 'h'},
+ {"version", no_argument, nullptr, 'v'},
+ {"input", required_argument, nullptr, 'i'},
+ {"input-include", required_argument, nullptr, 'I'},
+ {"upstream", required_argument, nullptr, 'u'},
+ {"upstream-include", required_argument, nullptr, 'U'},
+ {"allowlist", required_argument, nullptr, 'a'},
+ {"upstream-root-message", required_argument, nullptr, 'r'},
+ {"output", required_argument, nullptr, 'o'},
+ {nullptr, 0, nullptr, 0}};
+
+ std::string input;
+ std::string input_include;
+ std::string upstream;
+ std::string upstream_include;
+ std::string allowlist;
+ std::string upstream_root_message;
+ std::string output;
+
+ for (;;) {
+ int option =
+ getopt_long(argc, argv, "hvi:I:u:U:a:r:o:", long_options, nullptr);
+
+ if (option == -1)
+ break; // EOF.
+
+ if (option == 'v') {
+ printf("%s\n", base::GetVersionString());
+ return 0;
+ }
+
+ if (option == 'i') {
+ input = optarg;
+ continue;
+ }
+
+ if (option == 'I') {
+ input_include = optarg;
+ continue;
+ }
+
+ if (option == 'u') {
+ upstream = optarg;
+ continue;
+ }
+
+ if (option == 'U') {
+ upstream_include = optarg;
+ continue;
+ }
+
+ if (option == 'a') {
+ allowlist = optarg;
+ continue;
+ }
+
+ if (option == 'r') {
+ upstream_root_message = optarg;
+ continue;
+ }
+
+ if (option == 'o') {
+ output = optarg;
+ continue;
+ }
+
+ if (option == 'h') {
+ fprintf(stdout, kUsage);
+ return 0;
+ }
+
+ fprintf(stderr, kUsage);
+ return 1;
+ }
+
+ if (input.empty()) {
+ PERFETTO_ELOG("Input proto (--input) should be specified");
+ return 1;
+ }
+
+ if (input_include.empty()) {
+ PERFETTO_ELOG(
+ "Input include directory (--input-include) should be specified");
+ return 1;
+ }
+
+ if (upstream.empty()) {
+ PERFETTO_ELOG("Upstream proto (--upstream) should be specified");
+ return 1;
+ }
+
+ if (upstream_include.empty()) {
+ PERFETTO_ELOG(
+ "Upstream include directory (--upstream-include) should be specified");
+ return 1;
+ }
+
+ if (output.empty()) {
+ PERFETTO_ELOG("Output file (--output) should be specified");
+ return 1;
+ }
+
+ if (!allowlist.empty() && upstream_root_message.empty()) {
+ PERFETTO_ELOG(
+ "Need to specifiy upstream root message (--upstream-root-message) when "
+ "specifying allowlist");
+ return 1;
+ }
+
+ ImportResult input_proto = ImportProto(input, input_include);
+ ProtoFile input_file = ProtoFileFromDescriptor(*input_proto.file_descriptor);
+
+ ImportResult upstream_proto = ImportProto(upstream, upstream_include);
+ ProtoFile upstream_file =
+ ProtoFileFromDescriptor(*upstream_proto.file_descriptor);
+
+ Allowlist allowed;
+ if (!allowlist.empty()) {
+ std::string allowlist_contents;
+ if (!base::ReadFile(allowlist, &allowlist_contents)) {
+ PERFETTO_ELOG("Failed to read allowlist");
+ return 1;
+ }
+
+ auto* desc = upstream_proto.importer->pool()->FindMessageTypeByName(
+ upstream_root_message);
+ if (!desc) {
+ PERFETTO_ELOG(
+ "Failed to find root message descriptor in upstream proto file");
+ return 1;
+ }
+
+ auto field_list = base::SplitString(allowlist_contents, "\n");
+ base::Status status = AllowlistFromFieldList(*desc, field_list, allowed);
+ if (!status.ok()) {
+ PERFETTO_ELOG("Failed creating allowlist: %s", status.c_message());
+ return 1;
+ }
+ }
+
+ ProtoFile merged;
+ base::Status status =
+ MergeProtoFiles(input_file, upstream_file, allowed, merged);
+ if (!status.ok()) {
+ PERFETTO_ELOG("Failed merging protos: %s", status.c_message());
+ return 1;
+ }
+
+ base::ScopedFile output_file(
+ base::OpenFile(output, O_CREAT | O_WRONLY | O_TRUNC, 0664));
+ if (!output_file) {
+ PERFETTO_ELOG("Failed opening output file: %s", output.c_str());
+ return 1;
+ }
+ std::string out = ProtoFileToDotProto(merged);
+ base::WriteAll(*output_file, out.c_str(), out.size());
+
+ return 0;
+}
+
+} // namespace
+} // namespace proto_merger
+} // namespace perfetto
+
+int main(int argc, char** argv) {
+ return perfetto::proto_merger::Main(argc, argv);
+}
diff --git a/tools/proto_merger/proto_file.cc b/tools/proto_merger/proto_file.cc
new file mode 100644
index 0000000..e51018c
--- /dev/null
+++ b/tools/proto_merger/proto_file.cc
@@ -0,0 +1,278 @@
+/*
+ * 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 "tools/proto_merger/proto_file.h"
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/text_format.h>
+
+#include "perfetto/ext/base/string_utils.h"
+
+namespace perfetto {
+namespace proto_merger {
+namespace {
+
+const char* const
+ kTypeToName[google::protobuf::FieldDescriptor::Type::MAX_TYPE + 1] = {
+ "ERROR", // 0 is reserved for errors
+
+ "double", // TYPE_DOUBLE
+ "float", // TYPE_FLOAT
+ "int64", // TYPE_INT64
+ "uint64", // TYPE_UINT64
+ "int32", // TYPE_INT32
+ "fixed64", // TYPE_FIXED64
+ "fixed32", // TYPE_FIXED32
+ "bool", // TYPE_BOOL
+ "string", // TYPE_STRING
+ "group", // TYPE_GROUP
+ "message", // TYPE_MESSAGE
+ "bytes", // TYPE_BYTES
+ "uint32", // TYPE_UINT32
+ "enum", // TYPE_ENUM
+ "sfixed32", // TYPE_SFIXED32
+ "sfixed64", // TYPE_SFIXED64
+ "sint32", // TYPE_SINT32
+ "sint64", // TYPE_SINT64
+};
+
+const char* const
+ kLabelToName[google::protobuf::FieldDescriptor::MAX_LABEL + 1] = {
+ "ERROR", // 0 is reserved for errors
+
+ "optional", // LABEL_OPTIONAL
+ "required", // LABEL_REQUIRED
+ "repeated", // LABEL_REPEATED
+};
+
+base::Optional<std::string> MinimizeType(const std::string& a,
+ const std::string& b) {
+ auto a_pieces = base::SplitString(a, ".");
+ auto b_pieces = base::SplitString(b, ".");
+
+ size_t skip = 0;
+ for (size_t i = 0; i < std::min(a_pieces.size(), b_pieces.size()); ++i) {
+ if (a_pieces[i] != b_pieces[i])
+ return a.substr(skip);
+ skip += a_pieces[i].size() + 1;
+ }
+ return base::nullopt;
+}
+
+std::string SimpleFieldTypeFromDescriptor(
+ const google::protobuf::Descriptor& parent,
+ const google::protobuf::FieldDescriptor& desc,
+ bool packageless_type) {
+ switch (desc.type()) {
+ case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
+ if (packageless_type) {
+ return base::StripPrefix(desc.message_type()->full_name(),
+ desc.message_type()->file()->package() + ".");
+ } else {
+ return MinimizeType(desc.message_type()->full_name(),
+ parent.full_name())
+ .value_or(desc.message_type()->name());
+ }
+ case google::protobuf::FieldDescriptor::TYPE_ENUM:
+ if (packageless_type) {
+ return base::StripPrefix(desc.enum_type()->full_name(),
+ desc.enum_type()->file()->package() + ".");
+ } else {
+ return MinimizeType(desc.enum_type()->full_name(), parent.full_name())
+ .value_or(desc.enum_type()->name());
+ }
+ default:
+ return kTypeToName[desc.type()];
+ }
+}
+
+std::string FieldTypeFromDescriptor(
+ const google::protobuf::Descriptor& parent,
+ const google::protobuf::FieldDescriptor& desc,
+ bool packageless_type) {
+ if (!desc.is_map())
+ return SimpleFieldTypeFromDescriptor(parent, desc, packageless_type);
+
+ std::string field_type;
+ field_type += "map<";
+ field_type += FieldTypeFromDescriptor(parent, *desc.message_type()->field(0),
+ packageless_type);
+ field_type += ",";
+ field_type += FieldTypeFromDescriptor(parent, *desc.message_type()->field(1),
+ packageless_type);
+ field_type += ">";
+ return field_type;
+}
+
+std::unique_ptr<google::protobuf::Message> NormalizeOptionsMessage(
+ const google::protobuf::DescriptorPool& pool,
+ google::protobuf::DynamicMessageFactory* factory,
+ const google::protobuf::Message& message) {
+ const auto* option_descriptor =
+ pool.FindMessageTypeByName(message.GetDescriptor()->full_name());
+ if (!option_descriptor)
+ return nullptr;
+
+ std::unique_ptr<google::protobuf::Message> dynamic_options(
+ factory->GetPrototype(option_descriptor)->New());
+ PERFETTO_CHECK(dynamic_options->ParseFromString(message.SerializeAsString()));
+ return dynamic_options;
+}
+
+std::vector<ProtoFile::Option> OptionsFromMessage(
+ const google::protobuf::DescriptorPool& pool,
+ const google::protobuf::Message& raw_message) {
+ google::protobuf::DynamicMessageFactory factory;
+
+ auto normalized = NormalizeOptionsMessage(pool, &factory, raw_message);
+ const auto* message = normalized ? normalized.get() : &raw_message;
+ const auto* reflection = message->GetReflection();
+
+ std::vector<const google::protobuf::FieldDescriptor*> fields;
+ reflection->ListFields(*message, &fields);
+
+ std::vector<ProtoFile::Option> options;
+ for (size_t i = 0; i < fields.size(); i++) {
+ int count = 1;
+ bool repeated = false;
+ if (fields[i]->is_repeated()) {
+ count = reflection->FieldSize(*message, fields[i]);
+ repeated = true;
+ }
+ for (int j = 0; j < count; j++) {
+ std::string name;
+ if (fields[i]->is_extension()) {
+ name = "(" + fields[i]->full_name() + ")";
+ } else {
+ name = fields[i]->name();
+ }
+
+ std::string fieldval;
+ if (fields[i]->cpp_type() ==
+ google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+ std::string tmp;
+ google::protobuf::TextFormat::Printer printer;
+ printer.PrintFieldValueToString(*message, fields[i], repeated ? j : -1,
+ &tmp);
+ fieldval.append("{\n");
+ fieldval.append(tmp);
+ fieldval.append("}");
+ } else {
+ google::protobuf::TextFormat::PrintFieldValueToString(
+ *message, fields[i], repeated ? j : -1, &fieldval);
+ }
+ options.push_back(ProtoFile::Option{name, fieldval});
+ }
+ }
+ return options;
+}
+
+template <typename Output, typename Descriptor>
+Output InitFromDescriptor(const Descriptor& desc) {
+ google::protobuf::SourceLocation source_loc;
+ if (!desc.GetSourceLocation(&source_loc))
+ return {};
+
+ Output out;
+ out.leading_comments = base::SplitString(source_loc.leading_comments, "\n");
+ out.trailing_comments = base::SplitString(source_loc.trailing_comments, "\n");
+ return out;
+}
+
+ProtoFile::Field FieldFromDescriptor(
+ const google::protobuf::Descriptor& parent,
+ const google::protobuf::FieldDescriptor& desc) {
+ auto field = InitFromDescriptor<ProtoFile::Field>(desc);
+ field.label = kLabelToName[desc.label()];
+ field.packageless_type = FieldTypeFromDescriptor(parent, desc, true);
+ field.type = FieldTypeFromDescriptor(parent, desc, false);
+ field.name = desc.name();
+ field.number = desc.number();
+ field.options = OptionsFromMessage(*desc.file()->pool(), desc.options());
+ return field;
+}
+
+ProtoFile::Enum::Value EnumValueFromDescriptor(
+ const google::protobuf::EnumValueDescriptor& desc) {
+ auto value = InitFromDescriptor<ProtoFile::Enum::Value>(desc);
+ value.name = desc.name();
+ value.number = desc.number();
+ value.options = OptionsFromMessage(*desc.file()->pool(), desc.options());
+ return value;
+}
+
+ProtoFile::Enum EnumFromDescriptor(
+ const google::protobuf::EnumDescriptor& desc) {
+ auto en = InitFromDescriptor<ProtoFile::Enum>(desc);
+ en.name = desc.name();
+ for (int i = 0; i < desc.value_count(); ++i) {
+ en.values.emplace_back(EnumValueFromDescriptor(*desc.value(i)));
+ }
+ return en;
+}
+
+ProtoFile::Oneof OneOfFromDescriptor(
+ const google::protobuf::Descriptor& parent,
+ const google::protobuf::OneofDescriptor& desc) {
+ auto oneof = InitFromDescriptor<ProtoFile::Oneof>(desc);
+ oneof.name = desc.name();
+ for (int i = 0; i < desc.field_count(); ++i) {
+ oneof.fields.emplace_back(FieldFromDescriptor(parent, *desc.field(i)));
+ }
+ return oneof;
+}
+
+ProtoFile::Message MessageFromDescriptor(
+ const google::protobuf::Descriptor& desc) {
+ auto message = InitFromDescriptor<ProtoFile::Message>(desc);
+ message.name = desc.name();
+ for (int i = 0; i < desc.enum_type_count(); ++i) {
+ message.enums.emplace_back(EnumFromDescriptor(*desc.enum_type(i)));
+ }
+ for (int i = 0; i < desc.nested_type_count(); ++i) {
+ message.nested_messages.emplace_back(
+ MessageFromDescriptor(*desc.nested_type(i)));
+ }
+ for (int i = 0; i < desc.oneof_decl_count(); ++i) {
+ message.oneofs.emplace_back(OneOfFromDescriptor(desc, *desc.oneof_decl(i)));
+ }
+ for (int i = 0; i < desc.field_count(); ++i) {
+ auto* field = desc.field(i);
+ if (field->containing_oneof())
+ continue;
+ message.fields.emplace_back(FieldFromDescriptor(desc, *field));
+ }
+ return message;
+}
+
+} // namespace
+
+ProtoFile ProtoFileFromDescriptor(
+ const google::protobuf::FileDescriptor& desc) {
+ ProtoFile file;
+ for (int i = 0; i < desc.enum_type_count(); ++i) {
+ file.enums.push_back(EnumFromDescriptor(*desc.enum_type(i)));
+ }
+ for (int i = 0; i < desc.message_type_count(); ++i) {
+ file.messages.push_back(MessageFromDescriptor(*desc.message_type(i)));
+ }
+ return file;
+}
+
+} // namespace proto_merger
+} // namespace perfetto
diff --git a/tools/proto_merger/proto_file.h b/tools/proto_merger/proto_file.h
new file mode 100644
index 0000000..3e48bd9
--- /dev/null
+++ b/tools/proto_merger/proto_file.h
@@ -0,0 +1,91 @@
+/*
+ * 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 TOOLS_PROTO_MERGER_PROTO_FILE_H_
+#define TOOLS_PROTO_MERGER_PROTO_FILE_H_
+
+#include <string>
+#include <vector>
+
+// We include this intentionally instead of forward declaring to allow
+// for an easy find/replace transformation when moving to Google3.
+#include <google/protobuf/descriptor.h>
+
+namespace perfetto {
+namespace proto_merger {
+
+/// Simplified representation of the coomponents of a .proto file.
+struct ProtoFile {
+ struct Option {
+ std::string key;
+ std::string value;
+ };
+ struct Member {
+ std::vector<std::string> leading_comments;
+ std::vector<std::string> trailing_comments;
+ };
+ struct Enum : Member {
+ struct Value : Member {
+ std::string name;
+ int number;
+ std::vector<Option> options;
+ };
+ std::string name;
+ std::vector<Value> values;
+
+ std::vector<Value> deleted_values;
+ };
+ struct Field : Member {
+ std::string label;
+ std::string packageless_type;
+ std::string type;
+ std::string name;
+ int number;
+ std::vector<Option> options;
+ };
+ struct Oneof : Member {
+ std::string name;
+ std::vector<Field> fields;
+
+ std::vector<Field> deleted_fields;
+ };
+ struct Message : Member {
+ std::string name;
+ std::vector<Enum> enums;
+ std::vector<Message> nested_messages;
+ std::vector<Oneof> oneofs;
+ std::vector<Field> fields;
+
+ std::vector<Enum> deleted_enums;
+ std::vector<Message> deleted_nested_messages;
+ std::vector<Oneof> deleted_oneofs;
+ std::vector<Field> deleted_fields;
+ };
+
+ std::vector<Message> messages;
+ std::vector<Enum> enums;
+
+ std::vector<Message> deleted_messages;
+ std::vector<Enum> deleted_enums;
+};
+
+// Creates a ProtoFile struct from a libprotobuf-full descriptor clas.
+ProtoFile ProtoFileFromDescriptor(const google::protobuf::FileDescriptor&);
+
+} // namespace proto_merger
+} // namespace perfetto
+
+#endif // TOOLS_PROTO_MERGER_PROTO_FILE_H_
diff --git a/tools/proto_merger/proto_file_serializer.cc b/tools/proto_merger/proto_file_serializer.cc
new file mode 100644
index 0000000..82232b2
--- /dev/null
+++ b/tools/proto_merger/proto_file_serializer.cc
@@ -0,0 +1,222 @@
+/*
+ * 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 "tools/proto_merger/proto_file_serializer.h"
+
+#include "perfetto/ext/base/string_utils.h"
+
+namespace perfetto {
+namespace proto_merger {
+namespace {
+
+std::string DeletedComment(const std::string& prefix) {
+ std::string output;
+ output += "\n";
+ output += prefix + " //\n";
+ output += prefix;
+ output +=
+ " // The following enums/messages/fields are not present upstream\n";
+ output += prefix + " //\n";
+ return output;
+}
+
+std::string SerializeComments(const std::string& prefix,
+ const std::vector<std::string>& lines) {
+ std::string output;
+ for (const auto& line : lines) {
+ output.append(prefix);
+ output.append("//");
+ output.append(line);
+ output.append("\n");
+ }
+ return output;
+}
+
+std::string SerializeLeadingComments(const std::string& prefix,
+ const ProtoFile::Member& member,
+ bool prefix_newline_if_comment = true) {
+ if (member.leading_comments.empty())
+ return "";
+
+ std::string output;
+ if (prefix_newline_if_comment) {
+ output += "\n";
+ }
+ output += SerializeComments(prefix, member.leading_comments);
+ return output;
+}
+
+std::string SerializeTrailingComments(const std::string& prefix,
+ const ProtoFile::Member& member) {
+ return SerializeComments(prefix, member.trailing_comments);
+}
+
+std::string SerializeOptions(const std::vector<ProtoFile::Option>& options) {
+ if (options.empty())
+ return "";
+
+ std::string output;
+ output += " [";
+ for (const auto& option : options) {
+ output += option.key + " = " + option.value;
+ }
+ output += "]";
+ return output;
+}
+
+std::string SerializeEnumValue(size_t indent,
+ const ProtoFile::Enum::Value& value) {
+ std::string prefix(indent * 2, ' ');
+
+ std::string output;
+ output += SerializeLeadingComments(prefix, value, false);
+
+ output += prefix + value.name + " = " + std::to_string(value.number);
+ output += SerializeOptions(value.options);
+ output += ";\n";
+
+ output += SerializeTrailingComments(prefix, value);
+ return output;
+}
+
+std::string SerializeEnum(size_t indent, const ProtoFile::Enum& en) {
+ std::string prefix(indent * 2, ' ');
+ ++indent;
+
+ std::string output;
+ output += SerializeLeadingComments(prefix, en);
+
+ output += prefix + "enum " + en.name + " {\n";
+ for (const auto& value : en.values) {
+ output += SerializeEnumValue(indent, value);
+ }
+ output += prefix + "}\n";
+
+ output += SerializeTrailingComments(prefix, en);
+ return output;
+}
+
+std::string SerializeField(size_t indent,
+ const ProtoFile::Field& field,
+ bool write_label) {
+ std::string prefix(indent * 2, ' ');
+
+ std::string output;
+ output += SerializeLeadingComments(prefix, field);
+
+ std::string label;
+ if (write_label) {
+ label = field.label + " ";
+ }
+ output += prefix + label + field.type + " " + field.name + " = " +
+ std::to_string(field.number);
+
+ output += SerializeOptions(field.options);
+ output += ";\n";
+
+ output += SerializeTrailingComments(prefix, field);
+ return output;
+}
+
+std::string SerializeOneof(size_t indent, const ProtoFile::Oneof& oneof) {
+ std::string prefix(indent * 2, ' ');
+ ++indent;
+
+ std::string output;
+ output += SerializeLeadingComments(prefix, oneof);
+
+ output += prefix + "oneof " + oneof.name + " {\n";
+ for (const auto& field : oneof.fields) {
+ output += SerializeField(indent, field, false);
+ }
+ output += prefix + "}\n";
+
+ output += SerializeTrailingComments(prefix, oneof);
+ return output;
+}
+
+std::string SerializeMessage(size_t indent, const ProtoFile::Message& message) {
+ std::string prefix(indent * 2, ' ');
+ ++indent;
+
+ std::string output;
+ output += SerializeLeadingComments(prefix, message);
+
+ output += prefix + "message " + message.name + " {\n";
+ for (const auto& en : message.enums) {
+ output += SerializeEnum(indent, en);
+ }
+ for (const auto& nested : message.nested_messages) {
+ output += SerializeMessage(indent, nested);
+ }
+ for (const auto& oneof : message.oneofs) {
+ output += SerializeOneof(indent, oneof);
+ }
+ for (const auto& field : message.fields) {
+ output += SerializeField(indent, field, true);
+ }
+
+ if (!message.deleted_enums.empty() || !message.deleted_fields.empty() ||
+ !message.deleted_nested_messages.empty() ||
+ !message.deleted_oneofs.empty()) {
+ output += DeletedComment(prefix);
+ for (const auto& en : message.deleted_enums) {
+ output += SerializeEnum(indent, en);
+ }
+ for (const auto& nested : message.deleted_nested_messages) {
+ output += SerializeMessage(indent, nested);
+ }
+ for (const auto& oneof : message.deleted_oneofs) {
+ output += SerializeOneof(indent, oneof);
+ }
+ for (const auto& field : message.deleted_fields) {
+ output += SerializeField(indent, field, true);
+ }
+ }
+
+ output += prefix + "}\n";
+
+ output += SerializeTrailingComments(prefix, message);
+ return output;
+}
+
+} // namespace
+
+std::string ProtoFileToDotProto(const ProtoFile& proto_file) {
+ std::string output;
+ for (const auto& en : proto_file.enums) {
+ output += SerializeEnum(0, en);
+ }
+ for (const auto& message : proto_file.messages) {
+ output += SerializeMessage(0, message);
+ }
+
+ if (!proto_file.deleted_enums.empty() ||
+ !proto_file.deleted_messages.empty()) {
+ output += DeletedComment("");
+
+ for (const auto& en : proto_file.deleted_enums) {
+ output += SerializeEnum(0, en);
+ }
+ for (const auto& nested : proto_file.deleted_messages) {
+ output += SerializeMessage(0, nested);
+ }
+ }
+ return output;
+}
+
+} // namespace proto_merger
+} // namespace perfetto
diff --git a/tools/proto_merger/proto_file_serializer.h b/tools/proto_merger/proto_file_serializer.h
new file mode 100644
index 0000000..23addad
--- /dev/null
+++ b/tools/proto_merger/proto_file_serializer.h
@@ -0,0 +1,61 @@
+/*
+ * 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 TOOLS_PROTO_MERGER_PROTO_FILE_SERIALIZER_H_
+#define TOOLS_PROTO_MERGER_PROTO_FILE_SERIALIZER_H_
+
+#include "tools/proto_merger/proto_file.h"
+
+namespace perfetto {
+namespace proto_merger {
+
+// Serializes a ProtoFile struct into a .proto file which is
+// capable of being parsed by protoc.
+// For example:
+// ProtoFile {
+// messages: [
+// Message {
+// name: Baz
+// fields: [
+// Field {
+// label: optional
+// type: Foo
+// name: foo
+// number: 1
+// }
+// Field {
+// label: optional
+// type: Bar
+// name: bar
+// number: 2
+// }
+// ]
+// }
+// ]
+// }
+//
+// will convert to:
+//
+// message Baz {
+// optional Foo foo = 1;
+// optonal Bar bar = 2;
+// }
+std::string ProtoFileToDotProto(const ProtoFile&);
+
+} // namespace proto_merger
+} // namespace perfetto
+
+#endif // TOOLS_PROTO_MERGER_PROTO_FILE_SERIALIZER_H_
diff --git a/tools/proto_merger/proto_merger.cc b/tools/proto_merger/proto_merger.cc
new file mode 100644
index 0000000..c362d59
--- /dev/null
+++ b/tools/proto_merger/proto_merger.cc
@@ -0,0 +1,357 @@
+/*
+ * 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 "tools/proto_merger/proto_merger.h"
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/optional.h"
+
+namespace perfetto {
+namespace proto_merger {
+namespace {
+
+template <typename Key, typename Value>
+base::Optional<Value> FindInMap(const std::map<Key, Value>& map,
+ const Key& key) {
+ auto it = map.find(key);
+ return it == map.end() ? base::nullopt : base::make_optional(it->second);
+}
+
+// Finds the given 'name' in the vector by comparing against
+// the field named 'name' for each item in the vector.
+// T is ProtoFile::Enum, ProtoFile::Oneof or ProtoFile::Message.
+template <typename T>
+const T* FindByName(const std::vector<T>& items, const std::string& name) {
+ for (const auto& item : items) {
+ if (item.name == name)
+ return &item;
+ }
+ return nullptr;
+}
+
+// Compute the items present in the |input| vector but deleted in
+// the |upstream| vector by looking at the field |name|.
+// T is ProtoFile::Enum, ProtoFile::Oneof or ProtoFile::Message.
+template <typename T>
+std::vector<T> ComputeDeletedByName(const std::vector<T>& input,
+ const std::vector<T>& upstream) {
+ std::vector<T> deleted;
+ std::set<std::string> seen;
+ for (const auto& upstream_item : upstream) {
+ auto* input_item = FindByName(input, upstream_item.name);
+ if (!input_item)
+ continue;
+ seen.insert(input_item->name);
+ }
+
+ for (const auto& input_item : input) {
+ if (seen.count(input_item.name))
+ continue;
+ deleted.emplace_back(input_item);
+ }
+ return deleted;
+}
+
+// Finds the given 'number' in the vector by comparing against
+// the field named 'number for each item in the vector.
+// T is ProtoFile::EnumValue or ProtoFile::Field.
+template <typename T>
+const T* FindByNumber(const std::vector<T>& items, int number) {
+ for (const auto& item : items) {
+ if (item.number == number)
+ return &item;
+ }
+ return nullptr;
+}
+
+// Compute the items present in the |input| vector but deleted in
+// the |upstream| vector by looking at the field |number|.
+// T is ProtoFile::EnumValue or ProtoFile::Field.
+template <typename T>
+std::vector<T> ComputeDeletedByNumber(const std::vector<T>& input,
+ const std::vector<T>& upstream) {
+ std::vector<T> deleted;
+ std::set<int> seen;
+ for (const auto& upstream_item : upstream) {
+ auto* input_item = FindByNumber(input, upstream_item.number);
+ if (!input_item)
+ continue;
+ seen.insert(input_item->number);
+ }
+
+ for (const auto& input_item : input) {
+ if (seen.count(input_item.number))
+ continue;
+ deleted.emplace_back(input_item);
+ }
+ return deleted;
+}
+
+ProtoFile::Enum::Value MergeEnumValue(const ProtoFile::Enum::Value& input,
+ const ProtoFile::Enum::Value& upstream) {
+ PERFETTO_CHECK(input.number == upstream.number);
+
+ ProtoFile::Enum::Value out;
+ out.name = upstream.name;
+
+ // Get the comments from the source of truth.
+ out.leading_comments = upstream.leading_comments;
+ out.trailing_comments = upstream.trailing_comments;
+
+ // Get everything else from the input.
+ out.number = input.number;
+ out.options = input.options;
+ return out;
+}
+
+ProtoFile::Enum MergeEnum(const ProtoFile::Enum& input,
+ const ProtoFile::Enum& upstream) {
+ PERFETTO_CHECK(input.name == upstream.name);
+
+ ProtoFile::Enum out;
+ out.name = upstream.name;
+
+ // Get the comments from the source of truth.
+ out.leading_comments = upstream.leading_comments;
+ out.trailing_comments = upstream.trailing_comments;
+
+ for (const auto& upstream_value : upstream.values) {
+ // If an enum is allowlisted, we implicitly assume that all its
+ // values are also allowed. Therefore, if the value doesn't exist
+ // in the input, just take it from the source of truth.
+ auto* input_value = FindByNumber(input.values, upstream_value.number);
+ auto out_value = input_value ? MergeEnumValue(*input_value, upstream_value)
+ : upstream_value;
+ out.values.emplace_back(std::move(out_value));
+ }
+
+ // Compute all the values present in the input but deleted in the
+ // source of truth.
+ out.deleted_values = ComputeDeletedByNumber(input.values, upstream.values);
+ return out;
+}
+
+std::vector<ProtoFile::Enum> MergeEnums(
+ const std::vector<ProtoFile::Enum>& input,
+ const std::vector<ProtoFile::Enum>& upstream,
+ const std::set<std::string>& allowlist) {
+ std::vector<ProtoFile::Enum> out;
+ for (const auto& upstream_enum : upstream) {
+ auto* input_enum = FindByName(input, upstream_enum.name);
+ if (!input_enum) {
+ // If the enum is missing from the input but is present
+ // in the allowlist, take the whole enum from the
+ // source of truth.
+ if (allowlist.count(upstream_enum.name))
+ out.emplace_back(upstream_enum);
+ continue;
+ }
+
+ // Otherwise, merge the enums from the input and source of truth.
+ out.emplace_back(MergeEnum(*input_enum, upstream_enum));
+ }
+ return out;
+}
+
+base::Status MergeField(const ProtoFile::Field& input,
+ const ProtoFile::Field& upstream,
+ ProtoFile::Field& out) {
+ PERFETTO_CHECK(input.number == upstream.number);
+
+ if (input.packageless_type != upstream.packageless_type) {
+ return base::ErrStatus(
+ "The type of field with id %d and name %s (source of truth name: %s) "
+ "changed from %s to %s. Please resolve conflict manually before "
+ "rerunning.",
+ input.number, input.name.c_str(), upstream.name.c_str(),
+ input.packageless_type.c_str(), upstream.packageless_type.c_str());
+ }
+
+ // If the packageless type mathces, the type should also match.
+ PERFETTO_CHECK(input.type == upstream.type);
+
+ // Get the comments, label and the name from the source of truth.
+ out.leading_comments = upstream.leading_comments;
+ out.trailing_comments = upstream.trailing_comments;
+ out.label = upstream.label;
+ out.name = upstream.name;
+
+ // Get everything else from the input.
+ out.number = input.number;
+ out.options = input.options;
+ out.packageless_type = input.packageless_type;
+ out.type = input.type;
+
+ return base::OkStatus();
+}
+
+base::Status MergeFields(const std::vector<ProtoFile::Field>& input,
+ const std::vector<ProtoFile::Field>& upstream,
+ const std::set<int>& allowlist,
+ std::vector<ProtoFile::Field>& out) {
+ for (const auto& upstream_field : upstream) {
+ auto* input_field = FindByNumber(input, upstream_field.number);
+ if (!input_field) {
+ // If the field is missing from the input but is present
+ // in the allowlist, take the whole field from the
+ // source of truth.
+ if (allowlist.count(upstream_field.number))
+ out.emplace_back(upstream_field);
+ continue;
+ }
+
+ // Otherwise, merge the fields from the input and source of truth.
+ ProtoFile::Field out_field;
+ base::Status status = MergeField(*input_field, upstream_field, out_field);
+ if (!status.ok())
+ return status;
+ out.emplace_back(std::move(out_field));
+ }
+ return base::OkStatus();
+}
+
+// We call both of these just "Merge" so that |MergeRecursive| below can
+// reference them with the same name.
+base::Status Merge(const ProtoFile::Oneof& input,
+ const ProtoFile::Oneof& upstream,
+ const Allowlist::Oneof& allowlist,
+ ProtoFile::Oneof& out);
+
+base::Status Merge(const ProtoFile::Message& input,
+ const ProtoFile::Message& upstream,
+ const Allowlist::Message& allowlist,
+ ProtoFile::Message& out);
+
+template <typename T, typename AllowlistType>
+base::Status MergeRecursive(
+ const std::vector<T>& input,
+ const std::vector<T>& upstream,
+ const std::map<std::string, AllowlistType>& allowlist_map,
+ std::vector<T>& out) {
+ for (const auto& upstream_item : upstream) {
+ auto opt_allowlist = FindInMap(allowlist_map, upstream_item.name);
+ auto* input_item = FindByName(input, upstream_item.name);
+
+ // If the value is not present in the input and the allowlist doesn't
+ // exist either, this field is not approved so should not be included
+ // in the output.
+ if (!input_item && !opt_allowlist)
+ continue;
+
+ // If the input value doesn't exist, create a fake "input" that we can pass
+ // to the merge functon. This basically has the effect that the upstream
+ // item is taken but *not* recrusively; i.e. any fields which are inside the
+ // message/oneof are checked against the allowlist individually. If we just
+ // took the whole upstream here, we could add fields which were not
+ // allowlisted.
+ T input_or_fake;
+ if (input_item) {
+ input_or_fake = *input_item;
+ } else {
+ input_or_fake.name = upstream_item.name;
+ }
+
+ auto allowlist = opt_allowlist.value_or(AllowlistType{});
+ T out_item;
+ auto status = Merge(input_or_fake, upstream_item, allowlist, out_item);
+ if (!status.ok())
+ return status;
+ out.emplace_back(std::move(out_item));
+ }
+ return base::OkStatus();
+}
+
+base::Status Merge(const ProtoFile::Oneof& input,
+ const ProtoFile::Oneof& upstream,
+ const Allowlist::Oneof& allowlist,
+ ProtoFile::Oneof& out) {
+ PERFETTO_CHECK(input.name == upstream.name);
+ out.name = input.name;
+
+ // Get the comments from the source of truth.
+ out.leading_comments = upstream.leading_comments;
+ out.trailing_comments = upstream.trailing_comments;
+
+ // Compute all the fields present in the input but deleted in the
+ // source of truth.
+ out.deleted_fields = ComputeDeletedByNumber(input.fields, upstream.fields);
+
+ // Finish by merging the list of fields.
+ return MergeFields(input.fields, upstream.fields, allowlist, out.fields);
+}
+
+base::Status Merge(const ProtoFile::Message& input,
+ const ProtoFile::Message& upstream,
+ const Allowlist::Message& allowlist,
+ ProtoFile::Message& out) {
+ PERFETTO_CHECK(input.name == upstream.name);
+ out.name = input.name;
+
+ // Get the comments from the source of truth.
+ out.leading_comments = upstream.leading_comments;
+ out.trailing_comments = upstream.trailing_comments;
+
+ // Compute all the values present in the input but deleted in the
+ // source of truth.
+ out.deleted_enums = ComputeDeletedByName(input.enums, upstream.enums);
+ out.deleted_nested_messages =
+ ComputeDeletedByName(input.nested_messages, upstream.nested_messages);
+ out.deleted_oneofs = ComputeDeletedByName(input.oneofs, upstream.oneofs);
+ out.deleted_fields = ComputeDeletedByNumber(input.fields, upstream.fields);
+
+ // Merge any nested enum types.
+ out.enums = MergeEnums(input.enums, upstream.enums, allowlist.enums);
+
+ // Merge any nested message types.
+ auto status = MergeRecursive(input.nested_messages, upstream.nested_messages,
+ allowlist.nested_messages, out.nested_messages);
+ if (!status.ok())
+ return status;
+
+ // Merge any oneofs.
+ status = MergeRecursive(input.oneofs, upstream.oneofs, allowlist.oneofs,
+ out.oneofs);
+ if (!status.ok())
+ return status;
+
+ // Finish by merging the list of fields.
+ return MergeFields(input.fields, upstream.fields, allowlist.fields,
+ out.fields);
+}
+
+} // namespace
+
+base::Status MergeProtoFiles(const ProtoFile& input,
+ const ProtoFile& upstream,
+ const Allowlist& allowlist,
+ ProtoFile& out) {
+ // Compute all the enums and messages present in the input but deleted in the
+ // source of truth.
+ out.deleted_enums = ComputeDeletedByName(input.enums, upstream.enums);
+ out.deleted_messages =
+ ComputeDeletedByName(input.messages, upstream.messages);
+
+ // Merge the top-level enums.
+ out.enums = MergeEnums(input.enums, upstream.enums, allowlist.enums);
+
+ // Finish by merging the top-level messages.
+ return MergeRecursive(input.messages, upstream.messages, allowlist.messages,
+ out.messages);
+}
+
+} // namespace proto_merger
+} // namespace perfetto
diff --git a/tools/proto_merger/proto_merger.h b/tools/proto_merger/proto_merger.h
new file mode 100644
index 0000000..159aa35
--- /dev/null
+++ b/tools/proto_merger/proto_merger.h
@@ -0,0 +1,46 @@
+/*
+ * 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 TOOLS_PROTO_MERGER_PROTO_MERGER_H_
+#define TOOLS_PROTO_MERGER_PROTO_MERGER_H_
+
+#include "perfetto/base/status.h"
+#include "tools/proto_merger/allowlist.h"
+#include "tools/proto_merger/proto_file.h"
+
+namespace perfetto {
+namespace proto_merger {
+
+// Merges any updates in the proto |upstream| into the proto |input|
+// optionally adding any messages/fields/enums/values specified in the
+// the |allowlist|.
+//
+// Some notes about the merging algorithm:
+// * Comments for all values are always taken from |upstream|.
+// * If an enum is allowed, then so are all it's values.
+// * Options for fields are always taken from |input|; any new options in
+// |upstream| are ignored.
+// * Changing the type of an existing field is not supported (even if its
+// just a move); this needs to be handled manually.
+base::Status MergeProtoFiles(const ProtoFile& input,
+ const ProtoFile& upstream,
+ const Allowlist& allowlist,
+ ProtoFile& out);
+
+} // namespace proto_merger
+} // namespace perfetto
+
+#endif // TOOLS_PROTO_MERGER_PROTO_MERGER_H_
diff --git a/tools/record_android_trace b/tools/record_android_trace
index f4c2d4b..4dcb96d 100755
--- a/tools/record_android_trace
+++ b/tools/record_android_trace
@@ -33,16 +33,6 @@
# 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'
-# For downloading and sideloading tracebox on older devices, or when the
-# --sideload argument is passed.
-TRACEBOX_BASE_URL = 'https://storage.googleapis.com/perfetto/'
-TRACEBOX_SHA1S = {
- 'android-arm': '6e9dfee326468fc6858c6d95e00be110efd187a3', # v15.0.248
- 'android-arm64': 'ca2d4a02511f73dac32a2ae49964f3e5cd59d252', # v15.0.248
- 'android-x86': '3fdbc9246412e460d0a373140c114cff858b9b7c', # v15.0.248
- 'android-x64': 'be85f6f4a2d014d425246b85941c137c28d158cc', # v15.0.248
-}
-
# Translates the Android ro.product.cpu.abi into the GN's target_cpu.
ABI_TO_ARCH = {
'armeabi-v7a': 'arm',
@@ -152,9 +142,16 @@
help = 'Can be generated with https://ui.perfetto.dev/#!/record'
grp.add_argument('-c', '--config', default=None, help=help)
+
+ help = 'Specify the ADB device serial'
+ grp.add_argument('--serial', '-s', default=None, help=help)
+
args = parser.parse_args()
args.sideload = args.sideload or args.sideload_path is not None
+ if args.serial:
+ os.environ["ANDROID_SERIAL"] = args.serial
+
find_adb()
if args.list:
@@ -200,7 +197,9 @@
sys.exit(1)
shell_user = lines[2]
if api_level < 29 or args.sideload: # 29: Android Q.
- tracebox_bin = args.sideload_path or download_tracebox_if_needed(arch)
+ tracebox_bin = args.sideload_path
+ if tracebox_bin is None:
+ tracebox_bin = get_perfetto_prebuilt('tracebox', arch='android-' + arch)
perfetto_cmd = '/data/local/tmp/tracebox'
exit_code = adb('push', '--sync', tracebox_bin, perfetto_cmd).wait()
exit_code |= adb('shell', 'chmod 755 ' + perfetto_cmd).wait()
@@ -293,6 +292,7 @@
prt('\n')
prt('Pulling into %s' % host_file, ANSI.BOLD)
adb('pull', device_file, host_file).wait()
+ adb('shell', 'rm -f ' + device_file).wait()
if not args.no_open:
prt('\n')
@@ -362,26 +362,135 @@
return file_hash == sha_value
-def download_tracebox_if_needed(arch):
- sha_value = TRACEBOX_SHA1S.get('android-' + arch)
- if sha_value is None:
- prt('Unsupported architecture ' + arch)
- sys.exit(1)
- file_name = 'tracebox-android-' + arch + '-' + sha_value
- local_file = os.path.join(tempfile.gettempdir(), file_name)
- if os.path.exists(local_file):
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- else:
- return local_file
- url = TRACEBOX_BASE_URL + file_name
- prt('Downloading %s' % url)
- subprocess.check_call(['curl', '-L', '-#', '-o', local_file, url])
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- raise ValueError('Invalid SHA1 for %s' % local_file)
- return local_file
+# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
+# Revision: 387c10f55b96e95f96ec9248c3af28772bccfff0
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'android-arm',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1021824,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/android-arm/tracebox',
+ 'sha256':
+ 'de6362a183adf3d70ece245c083fd50b170061ffbcd878765052eea774198c4e'
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'android-arm64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1559112,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/android-arm64/tracebox',
+ 'sha256':
+ '90ee3858410ad3e57cd946d3734cba69c22f423c0d4d8d35c61c14c317b5293a'
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'android-x86',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1587028,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/android-x86/tracebox',
+ 'sha256':
+ 'c95b3d794e05462bc89d133ba7aca8a33032bab95d70ac43b24dbefe2db8c996'
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'android-x64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1829448,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/android-x64/tracebox',
+ 'sha256':
+ 'd1da3f3c95bd8685b5bd75af19137c8d952fc88bb691dfc2a7e00706f3837074'
+}]
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ print('Downloading ' + url)
+ subprocess.check_call(['curl', '-f', '-L', '-#', '-o', tmp_path, url])
+ with open(tmp_path, 'rb') as fd:
+ actual_sha256 = hashlib.sha256(fd.read()).hexdigest()
+ if actual_sha256 != sha256:
+ raise Exception('Checksum mismatch for %s (actual: %s, expected: %s)' %
+ (url, actual_sha256, sha256))
+ os.chmod(tmp_path, 0o755)
+ os.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and entry.get(
+ 'platform') == plat and machine in entry.get('machine', []):
+ manifest_entry = entry
+ break
+ if manifest_entry is None:
+ if soft_fail:
+ return None
+ raise Exception(
+ ('No prebuilts available for %s-%s\n' % (plat, machine)) +
+ 'See https://perfetto.dev/docs/contributing/build-instructions')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
+
+
+# END_SECTION_GENERATED_BY(roll-prebuilts)
+
if __name__ == '__main__':
sys.exit(main())
diff --git a/tools/roll-prebuilts b/tools/roll-prebuilts
new file mode 100755
index 0000000..abb1a29
--- /dev/null
+++ b/tools/roll-prebuilts
@@ -0,0 +1,184 @@
+#!/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.
+"""Updates the python scripts in tools/{trace_processor, traceconv, tracebox}
+
+This script does the following, for each entry in SCRIPTS_TO_UPDATE:
+ - Downloads the artifact by the LUCI infrastructure, one for each arch.
+ - Computes the SHA-256 of each artifact.
+ - Generates a manifest with URL, SHA-256 and other details.
+ - Merges get_perfetto_prebuilt.py with the manifest and writes tools/xxx.
+
+This script is supposed to be run by Perfetto OWNERS after every monthly release
+after the LUCI jobs have completed.
+"""
+
+import argparse
+import hashlib
+import logging
+import os
+import subprocess
+import sys
+
+from concurrent.futures import ThreadPoolExecutor
+
+GCS_URL = 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts'
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+TOOLS_DIR = os.path.join(ROOT_DIR, 'tools')
+
+SCRIPTS_TO_UPDATE = [
+ {
+ 'script':
+ 'trace_processor',
+ 'tool':
+ 'trace_processor_shell',
+ 'archs': [
+ 'mac-amd64', 'windows-amd64', 'linux-amd64', 'linux-arm',
+ 'linux-arm64'
+ ]
+ },
+ {
+ 'script': 'traceconv',
+ 'tool': 'trace_to_text',
+ 'archs': ['mac-amd64', 'linux-amd64', 'windows-amd64']
+ },
+ {
+ 'script':
+ 'tracebox',
+ 'tool':
+ 'tracebox',
+ 'archs': [
+ 'mac-amd64', 'linux-amd64', 'linux-amd64', 'linux-arm',
+ 'linux-arm64'
+ ]
+ },
+ {
+ 'script': 'heap_profile',
+ 'tool': 'trace_to_text',
+ 'archs': ['mac-amd64', 'windows-amd64', 'linux-amd64']
+ },
+ {
+ 'script': 'record_android_trace',
+ 'tool': 'tracebox',
+ 'archs': ['android-arm', 'android-arm64', 'android-x86', 'android-x64']
+ },
+]
+
+# Maps a 'os-arch' string (were arch follows LUCI conventions) into
+# corresponding tuples that match against python's platform / machine API
+# (see get_perfetto_prebuilt.py for usage).
+ARCH_TO_PYTHON = {
+ 'mac-amd64': {
+ 'platform': 'darwin',
+ 'machine': ['x86_64'],
+ },
+ 'windows-amd64': {
+ 'platform': 'win32',
+ 'machine': ['amd64'],
+ },
+ 'linux-amd64': {
+ 'platform': 'linux',
+ 'machine': ['x86_64'],
+ },
+ 'linux-arm': {
+ 'platform': 'linux',
+ 'machine': ['armv6l', 'armv7l', 'armv8l'],
+ },
+ 'linux-arm64': {
+ 'platform': 'linux',
+ 'machine': ['aarch64'],
+ },
+}
+
+
+def make_manifest(git_revision, tool, arch):
+ ext = '.exe' if arch.startswith('windows') else ''
+ file_name = tool + ext
+ url = '%s/%s/%s/%s' % (GCS_URL, git_revision, arch, file_name)
+ logging.info('Downloading %s', url)
+ data = subprocess.check_output(['curl', '-fsL', '-o', '-', url])
+ manifest = {
+ 'tool': tool,
+ 'arch': arch,
+ 'file_name': file_name,
+ 'file_size': len(data),
+ 'url': url,
+ 'sha256': hashlib.sha256(data).hexdigest()
+ }
+ manifest.update(ARCH_TO_PYTHON.get(arch, {}))
+ return manifest
+
+
+# Returns the section of get_perfetto_prebuilt.py which should be copy/pasted
+# in the various scripts.
+def read_get_perfetto_prebuilt_script():
+ in_file = os.path.join(TOOLS_DIR, 'get_perfetto_prebuilt.py')
+ with open(in_file, 'r') as f:
+ contents = f.read()
+ return contents.split('COPIED_SECTION_START_MARKER')[1]
+
+
+def update_script(git_revision, tool_name, script_name, archs):
+ with ThreadPoolExecutor(max_workers=8) as executor:
+ manifests = list(
+ executor.map(lambda arch: make_manifest(git_revision, tool_name, arch),
+ archs))
+ out_file = os.path.join(TOOLS_DIR, script_name)
+ with open(out_file) as f:
+ script = f.read()
+
+ begin_marker = '\n# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)\n'
+ end_marker = '\n# END_SECTION_GENERATED_BY(roll-prebuilts)\n'
+ before = script.partition(begin_marker)[0]
+ after = script.partition(end_marker)[2]
+
+ content = '# Revision: {git_revision}\n'
+ content += 'PERFETTO_PREBUILT_MANIFEST = {manifests}\n'
+ content += '{fn_body}\n'
+ content = content.format(
+ git_revision=git_revision,
+ manifests=str(manifests),
+ fn_body=read_get_perfetto_prebuilt_script())
+
+ script = before + begin_marker + content + end_marker + after
+
+ with open(out_file + '.tmp', 'w') as f:
+ f.write(script)
+ subprocess.check_call(['yapf', '-i', out_file + '.tmp'])
+ os.rename(out_file + '.tmp', out_file)
+ os.chmod(out_file, 0o755)
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-r', '--revision')
+ args = parser.parse_args()
+
+ if args.revision is None:
+ print('Error: must pass --revision=v1.2 or --revision=0a1b2c3d\n')
+ print('To list available revisions run')
+ print('gsutil ls gs://perfetto-luci-artifacts/')
+ print('or visit https://chrome-infra-packages.appspot.com/p/perfetto')
+ return 1
+
+ git_revision = args.revision
+ for spec in SCRIPTS_TO_UPDATE:
+ logging.info('Updating %s', spec['script'])
+ update_script(git_revision, spec['tool'], spec['script'], spec['archs'])
+
+
+if __name__ == '__main__':
+ logging.basicConfig(level=logging.INFO)
+ sys.exit(main())
diff --git a/tools/size-report b/tools/size-report
new file mode 100755
index 0000000..ef0a4a3
--- /dev/null
+++ b/tools/size-report
@@ -0,0 +1,106 @@
+#!/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.
+"""
+Generate a size report for target binaries.
+
+For example:
+$ tools/ninja -C out/r traced_probes traced
+$ tools/size-report.py -C out/r traced_probes traced
+"""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import argparse
+import os
+import subprocess
+import sys
+import json
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+BLOATY_PATH = os.path.join(ROOT_DIR, 'buildtools', 'bloaty', 'bloaty')
+GN_PATH = os.path.join(ROOT_DIR, 'tools', 'gn')
+
+def GetGnArgValueOrNone(arg):
+ if 'current' in arg:
+ return eval(arg['current']['value'])
+ if 'default' in arg:
+ return eval(arg['default']['value'])
+ return None
+
+
+def GetTargetOsForBuildDir(build_dir):
+ cmd = [GN_PATH, 'args', '--list', '--json', build_dir]
+ args = json.loads(subprocess.check_output(cmd))
+ target_os = None
+ host_os = None
+ for arg in args:
+ if arg['name'] == 'target_os':
+ print(arg)
+ target_os = GetGnArgValueOrNone(arg)
+ if arg['name'] == 'host_os':
+ print(arg)
+ host_os = GetGnArgValueOrNone(arg)
+ return target_os or host_os or None
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter, description=__doc__)
+ parser.add_argument(
+ '-C', '--build-dir', metavar='DIR', help='build directory', required=True)
+ parser.add_argument('-o', '--output', help='output path', default=None)
+ parser.add_argument(
+ 'binaries', metavar='BINARY', nargs='+', help='subjects of size report')
+ args = parser.parse_args()
+
+ if not os.path.exists(BLOATY_PATH):
+ print(
+ 'Could not find bloaty at expected path "{}". Try re-running ./tools/install-build-deps'
+ .format(BLOATY_PATH))
+ return 1
+
+ results = []
+
+ out_directory = args.build_dir
+ target_os = GetTargetOsForBuildDir(out_directory)
+ print('target_os', target_os)
+ for binary in args.binaries:
+ binary_path = os.path.join(out_directory, binary)
+ output = '{} - {}\n'.format(binary, binary_path)
+ if target_os == 'mac':
+ subprocess.check_output(['dsymutil', binary_path])
+ symbols = '--debug-file={}.dSYM/Contents/Resources/DWARF/{}'.format(
+ binary_path, binary)
+ cmd = [symbols, '-d', 'compileunits', '-n', '100', binary_path]
+ else:
+ cmd = ['-d', 'compileunits', '-n', '100', binary_path]
+ output += subprocess.check_output([BLOATY_PATH] + cmd).decode('utf-8')
+ results.append(output)
+
+ if args.output is None or args.output == '-':
+ out = sys.stdout
+ else:
+ out = open(args.output, 'w')
+
+ for result in results:
+ out.write(result)
+ out.write('\n')
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/tools/slice_breakdown/main.py b/tools/slice_breakdown/main.py
new file mode 100644
index 0000000..960e44b
--- /dev/null
+++ b/tools/slice_breakdown/main.py
@@ -0,0 +1,75 @@
+#!/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.
+""" Given a trace file, gives the self-time of userspace slices broken
+down by process, thread and thread state.
+"""
+
+import argparse
+import sys
+
+from perfetto.slice_breakdown import compute_breakdown, compute_breakdown_for_startup
+from perfetto.trace_processor import TraceProcessor
+
+
+def compute_breakdown_wrapper(args):
+ tp = TraceProcessor(
+ file_path=args.file, bin_path=args.shell_path, verbose=args.verbose)
+ if args.startup_bounds:
+ breakdown = compute_breakdown_for_startup(tp, args.startup_package,
+ args.process_name)
+ else:
+ breakdown = compute_breakdown(tp, args.start_ts, args.end_ts,
+ args.process_name)
+ tp.close()
+
+ return breakdown
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--file', required=True)
+ parser.add_argument('--shell-path', default=None)
+ parser.add_argument('--start-ts', default=None)
+ parser.add_argument('--end-ts', default=None)
+ parser.add_argument('--startup-bounds', action='store_true', default=False)
+ parser.add_argument('--startup-package', default=None)
+ parser.add_argument('--process-name', default=None)
+ parser.add_argument('--verbose', action='store_true', default=False)
+ parser.add_argument('--out-csv', required=True)
+ args = parser.parse_args()
+
+ if (args.start_ts or args.end_ts) and args.startup_bounds:
+ print("Cannot specify --start-ts or --end-ts and --startup-bounds")
+ return 1
+
+ if args.startup_package and not args.startup_bounds:
+ print("Must specify --startup-bounds if --startup-package is specified")
+ return 1
+
+ breakdown = compute_breakdown_wrapper(args)
+
+ if args.out_csv:
+ diff_csv = breakdown.to_csv(index=False)
+ if args.out_csv == '-':
+ sys.stdout.write(diff_csv)
+ else:
+ with open(args.out_csv, 'w') as out:
+ out.write(diff_csv)
+
+ return 0
+
+
+if __name__ == '__main__':
+ exit(main())
diff --git a/ui/run-tests b/tools/slice_breakdown/perfetto/slice_breakdown/__init__.py
old mode 100755
new mode 100644
similarity index 84%
copy from ui/run-tests
copy to tools/slice_breakdown/perfetto/slice_breakdown/__init__.py
index d06f7d2..6e6169f
--- a/ui/run-tests
+++ b/tools/slice_breakdown/perfetto/slice_breakdown/__init__.py
@@ -1,4 +1,3 @@
-#!/bin/bash
# Copyright (C) 2021 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,6 +12,4 @@
# 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 "$@"
+from .breakdown import compute_breakdown, compute_breakdown_for_startup
\ No newline at end of file
diff --git a/tools/slice_breakdown/perfetto/slice_breakdown/breakdown.py b/tools/slice_breakdown/perfetto/slice_breakdown/breakdown.py
new file mode 100644
index 0000000..85b21d2
--- /dev/null
+++ b/tools/slice_breakdown/perfetto/slice_breakdown/breakdown.py
@@ -0,0 +1,186 @@
+#!/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.
+
+
+def compute_breakdown(tp, start_ts=None, end_ts=None, process_name=None):
+ """For each userspace slice in the trace processor instance |tp|, computes
+ the self-time of that slice grouping by process name, thread name
+ and thread state.
+
+ Args:
+ tp: the trace processor instance to query.
+ start_ts: optional bound to only consider slices after this ts
+ end_ts: optional bound to only consider slices until this ts
+ process_name: optional process name to filter for slices; specifying
+ this argument can make computing the breakdown a lot faster.
+
+ Returns:
+ A Pandas dataframe containing the total self time taken by a slice stack
+ broken down by process name, thread name and thread state.
+ """
+ bounds = tp.query('SELECT * FROM trace_bounds').as_pandas_dataframe()
+ start_ts = start_ts if start_ts else bounds['start_ts'][0]
+ end_ts = end_ts if end_ts else bounds['end_ts'][0]
+
+ tp.query("""
+ DROP VIEW IF EXISTS modded_names
+ """)
+
+ tp.query("""
+ CREATE VIEW modded_names AS
+ SELECT
+ slice.id,
+ slice.depth,
+ slice.stack_id,
+ CASE
+ WHEN slice.name LIKE 'Choreographer#doFrame%'
+ THEN 'Choreographer#doFrame'
+ WHEN slice.name LIKE 'DrawFrames%'
+ THEN 'DrawFrames'
+ WHEN slice.name LIKE '/data/app%.apk'
+ THEN 'APK load'
+ WHEN slice.name LIKE 'OpenDexFilesFromOat%'
+ THEN 'OpenDexFilesFromOat'
+ WHEN slice.name LIKE 'Open oat file%'
+ THEN 'Open oat file'
+ ELSE slice.name
+ END AS modded_name
+ FROM slice
+ """)
+
+ tp.query("""
+ DROP VIEW IF EXISTS thread_slice_stack
+ """)
+
+ tp.query("""
+ CREATE VIEW thread_slice_stack AS
+ SELECT
+ efs.ts,
+ efs.dur,
+ IFNULL(n.stack_id, -1) AS stack_id,
+ t.utid,
+ IIF(efs.source_id IS NULL, '[No slice]', IFNULL(
+ (
+ SELECT GROUP_CONCAT(modded_name, ' > ')
+ FROM (
+ SELECT p.modded_name
+ FROM ancestor_slice(efs.source_id) a
+ JOIN modded_names p ON a.id = p.id
+ ORDER BY p.depth
+ )
+ ) || ' > ' || n.modded_name,
+ n.modded_name
+ )) AS stack_name
+ FROM experimental_flat_slice({}, {}) efs
+ LEFT JOIN modded_names n ON efs.source_id = n.id
+ JOIN thread_track t ON t.id = efs.track_id
+ """.format(start_ts, end_ts))
+
+ tp.query("""
+ DROP TABLE IF EXISTS thread_slice_stack_with_state
+ """)
+
+ tp.query("""
+ CREATE VIRTUAL TABLE thread_slice_stack_with_state
+ USING SPAN_JOIN(
+ thread_slice_stack PARTITIONED utid,
+ thread_state PARTITIONED utid
+ )
+ """)
+
+ if process_name:
+ where_process = "AND process.name = '{}'".format(process_name)
+ else:
+ where_process = ''
+
+ breakdown = tp.query("""
+ SELECT
+ process.name AS process_name,
+ thread.name AS thread_name,
+ CASE
+ WHEN slice.state = 'D' and slice.io_wait
+ THEN 'Uninterruptible sleep (IO)'
+ WHEN slice.state = 'DK' and slice.io_wait
+ THEN 'Uninterruptible sleep + Wake-kill (IO)'
+ WHEN slice.state = 'D' and not slice.io_wait
+ THEN 'Uninterruptible sleep (non-IO)'
+ WHEN slice.state = 'DK' and not slice.io_wait
+ THEN 'Uninterruptible sleep + Wake-kill (non-IO)'
+ WHEN slice.state = 'D'
+ THEN 'Uninterruptible sleep'
+ WHEN slice.state = 'DK'
+ THEN 'Uninterruptible sleep + Wake-kill'
+ WHEN slice.state = 'S' THEN 'Interruptible sleep'
+ WHEN slice.state = 'R' THEN 'Runnable'
+ WHEN slice.state = 'R+' THEN 'Runnable (Preempted)'
+ ELSE slice.state
+ END AS state,
+ slice.stack_name,
+ SUM(slice.dur)/1e6 AS dur_sum,
+ MIN(slice.dur/1e6) AS dur_min,
+ MAX(slice.dur/1e6) AS dur_max,
+ AVG(slice.dur/1e6) AS dur_mean,
+ PERCENTILE(slice.dur/1e6, 50) AS dur_median,
+ PERCENTILE(slice.dur/1e6, 25) AS dur_25_percentile,
+ PERCENTILE(slice.dur/1e6, 75) AS dur_75_percentile,
+ PERCENTILE(slice.dur/1e6, 95) AS dur_95_percentile,
+ PERCENTILE(slice.dur/1e6, 99) AS dur_99_percentile,
+ COUNT(1) as count
+ FROM process
+ JOIN thread USING (upid)
+ JOIN thread_slice_stack_with_state slice USING (utid)
+ WHERE dur != -1 {}
+ GROUP BY thread.name, stack_id, state
+ ORDER BY dur_sum DESC
+ """.format(where_process)).as_pandas_dataframe()
+
+ return breakdown
+
+
+def compute_breakdown_for_startup(tp, package_name=None, process_name=None):
+ """Computes the slice breakdown (like |compute_breakdown|) but only
+ considering slices which happened during an app startup
+
+ Args:
+ tp: the trace processor instance to query.
+ package_name: optional package name to filter for startups. Only a single
+ startup matching this package name should be present. If not specified,
+ only a single startup of any app should be in the trace.
+ process_name: optional process name to filter for slices; specifying
+ this argument can make computing the breakdown a lot faster.
+
+ Returns:
+ The same as |compute_breakdown| but only containing slices which happened
+ during app startup.
+ """
+ tp.metric(['android_startup'])
+
+ # Verify there was only one startup in the trace matching the package
+ # name.
+ filter = "WHERE package = '{}'".format(package_name) if package_name else ''
+ launches = tp.query('''
+ SELECT ts, ts_end, dur
+ FROM launches
+ {}
+ '''.format(filter)).as_pandas_dataframe()
+ if len(launches) == 0:
+ raise Exception("Didn't find startup in trace")
+ if len(launches) > 1:
+ raise Exception("Found multiple startups in trace")
+
+ start = launches['ts'][0]
+ end = launches['ts_end'][0]
+
+ return compute_breakdown(tp, start, end, process_name)
diff --git a/tools/symbolize-ui-crash b/tools/symbolize-ui-crash
index 3792ad0..77ea74c 100755
--- a/tools/symbolize-ui-crash
+++ b/tools/symbolize-ui-crash
@@ -23,8 +23,8 @@
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()
+https://android.googlesource.com/platform/external/perfetto/+/de4db33f/ui/src/foo.ts#61 at foo()
+https://android.googlesource.com/platform/external/perfetto/+/de4db33f/ui/src/baz.ts#300 at bar()
"""
import logging
@@ -42,6 +42,8 @@
sys.exit(1)
+GERRIT_BASE_URL = 'https://android.googlesource.com/platform/external/perfetto/'
+
def fetch_url_cached(url):
normalized = re.sub('[^a-zA-Z0-9-._]', '_', url)
local_file = os.path.join(tempfile.gettempdir(), normalized)
@@ -89,8 +91,7 @@
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_url = GERRIT_BASE_URL + '/+/%s/%s#%d' % (git_rev, src, sym.src_line)
sym_lines += sym_url + '\n'
txt = txt.replace(whole_token, sym_url)
diff --git a/tools/test_data.txt b/tools/test_data.txt
index 0585217..036f9a7 100644
--- a/tools/test_data.txt
+++ b/tools/test_data.txt
@@ -3,9 +3,11 @@
# The trailing /. at the end of a directory is to avoid creating a nesting
# directory when pushing a 2nd-time. adb push has a slightly different behavior
# than `cp` on directoriesm, trailing slash is not enough.
+src/profiling/memory/test/data/.
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
test/data/kallsyms.txt
+test/data/trace_with_uuid.pftrace
diff --git a/tools/tmux b/tools/tmux
index 51d1400..2129f4a 100755
--- a/tools/tmux
+++ b/tools/tmux
@@ -370,13 +370,13 @@
reset_tracing
TRACE=$TMPDIR/trace
-echo -e "\n\x1b[32mPulling trace into $TRACE.protobuf\x1b[0m"
-pull trace "$TRACE.protobuf"
+echo -e "\n\x1b[32mPulling trace into $TRACE.perfetto-trace\x1b[0m"
+pull trace "$TRACE.perfetto-trace"
if [[ SKIP_CONVERTERS -eq 0 ]]; then
echo -e "\n\x1b[32mPulling trace into $TRACE.pbtext\x1b[0m"
- "$OUT/trace_to_text" text <"$TRACE.protobuf" >"$TRACE.pbtext"
+ "$OUT/trace_to_text" text <"$TRACE.perfetto-trace" >"$TRACE.pbtext"
echo -e "\n\x1b[32mPulling trace into $TRACE.json\x1b[0m"
- "$OUT/trace_to_text" systrace <"$TRACE.protobuf" >"$TRACE.json"
+ "$OUT/trace_to_text" systrace <"$TRACE.perfetto-trace" >"$TRACE.json"
# Keep this last so it can fail.
fi
diff --git a/tools/trace_processor b/tools/trace_processor
index 22aaab6..8e17af5 100755
--- a/tools/trace_processor
+++ b/tools/trace_processor
@@ -24,73 +24,169 @@
exec python3 - "$@" <<'#'EOF
#"""
-import hashlib
-import os
-import sys
-import tempfile
-import subprocess
-import platform
+TOOL_NAME = 'trace_processor_shell'
-TRACE_PROCESSOR_SHELL_SHAS = {
- 'linux': 'a3ce2cbf4cbe4f86cc10b02957db727cecfafae8',
- 'mac': 'c39a5be9a3831911ef2e50d66d11c12d877688f3',
-}
-TRACE_PROCESSOR_SHELL_PATH = tempfile.gettempdir()
-TRACE_PROCESSOR_SHELL_BASE_URL = ('https://storage.googleapis.com/perfetto/')
+# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
+# Revision: 387c10f55b96e95f96ec9248c3af28772bccfff0
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool':
+ 'trace_processor_shell',
+ 'arch':
+ 'mac-amd64',
+ 'file_name':
+ 'trace_processor_shell',
+ 'file_size':
+ 7038736,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/mac-amd64/trace_processor_shell',
+ 'sha256':
+ '2d5d054d64af5c2b0f5649bbe653bb5d71a2b8465fc69d00d52abb818a093f83',
+ 'platform':
+ 'darwin',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'trace_processor_shell',
+ 'arch':
+ 'windows-amd64',
+ 'file_name':
+ 'trace_processor_shell.exe',
+ 'file_size':
+ 6671872,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/windows-amd64/trace_processor_shell.exe',
+ 'sha256':
+ 'f1438f5731b97770e4f80a6fbeb04841ed1ad6738dc15defeb69395e889581c6',
+ 'platform':
+ 'win32',
+ 'machine': ['amd64']
+}, {
+ 'tool':
+ 'trace_processor_shell',
+ 'arch':
+ 'linux-amd64',
+ 'file_name':
+ 'trace_processor_shell',
+ 'file_size':
+ 7386768,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/linux-amd64/trace_processor_shell',
+ 'sha256':
+ '643e9b4bbea808434b4630522241f9306d17f4669b8ccb3cf9a52d61b3871f5d',
+ 'platform':
+ 'linux',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'trace_processor_shell',
+ 'arch':
+ 'linux-arm',
+ 'file_name':
+ 'trace_processor_shell',
+ 'file_size':
+ 4640056,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/linux-arm/trace_processor_shell',
+ 'sha256':
+ '6118b0b863a9c9f04ea368fbec6aa6f482ccabb5abd7e8b94b31483bdb0f9d56',
+ 'platform':
+ 'linux',
+ 'machine': ['armv6l', 'armv7l', 'armv8l']
+}, {
+ 'tool':
+ 'trace_processor_shell',
+ 'arch':
+ 'linux-arm64',
+ 'file_name':
+ 'trace_processor_shell',
+ 'file_size':
+ 6171712,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/linux-arm64/trace_processor_shell',
+ 'sha256':
+ 'c1ed98c6104fb57b6452b1a01c3b8d8b9f25593eb85590f58de0efc8cf3c423d',
+ 'platform':
+ 'linux',
+ 'machine': ['aarch64']
+}]
-def DownloadURL(url, out_file):
- subprocess.check_call(['curl', '-L', '-#', '-o', out_file, url])
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ print('Downloading ' + url)
+ subprocess.check_call(['curl', '-f', '-L', '-#', '-o', tmp_path, url])
+ with open(tmp_path, 'rb') as fd:
+ actual_sha256 = hashlib.sha256(fd.read()).hexdigest()
+ if actual_sha256 != sha256:
+ raise Exception('Checksum mismatch for %s (actual: %s, expected: %s)' %
+ (url, actual_sha256, sha256))
+ os.chmod(tmp_path, 0o755)
+ os.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and entry.get(
+ 'platform') == plat and machine in entry.get('machine', []):
+ manifest_entry = entry
+ break
+ if manifest_entry is None:
+ if soft_fail:
+ return None
+ raise Exception(
+ ('No prebuilts available for %s-%s\n' % (plat, machine)) +
+ 'See https://perfetto.dev/docs/contributing/build-instructions')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
-def check_hash(file_name, sha_value):
- with open(file_name, 'rb') as fd:
- file_hash = hashlib.sha1(fd.read()).hexdigest()
- return file_hash == sha_value
-
-
-def load_trace_processor_shell(platform):
- sha_value = TRACE_PROCESSOR_SHELL_SHAS[platform]
- file_name = 'trace_processor_shell-' + platform + '-' + sha_value
- local_file = os.path.join(TRACE_PROCESSOR_SHELL_PATH, file_name)
-
- if os.path.exists(local_file):
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- else:
- return local_file
-
- url = TRACE_PROCESSOR_SHELL_BASE_URL + file_name
- DownloadURL(url, local_file)
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- raise ValueError("Invalid signature.")
- os.chmod(local_file, 0o755)
- return local_file
-
-
-def main(argv):
- os_name = None
- if sys.platform.startswith('linux'):
- os_name = 'linux'
- elif sys.platform.startswith('darwin'):
- os_name = '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)
- os.execv(trace_processor_shell_binary,
- [trace_processor_shell_binary] + argv[1:])
-
+# END_SECTION_GENERATED_BY(roll-prebuilts)
if __name__ == '__main__':
- sys.exit(main(sys.argv))
+ import sys, os
+ bin_path = get_perfetto_prebuilt(TOOL_NAME)
+ os.execv(bin_path, [bin_path] + sys.argv[1:])
#EOF
diff --git a/tools/trace_to_text/pprof_builder.cc b/tools/trace_to_text/pprof_builder.cc
index 588c438..b234f71 100644
--- a/tools/trace_to_text/pprof_builder.cc
+++ b/tools/trace_to_text/pprof_builder.cc
@@ -14,25 +14,22 @@
* limitations under the License.
*/
-#include "perfetto/base/build_config.h"
-
#include "perfetto/profiling/pprof_builder.h"
+#include "perfetto/base/build_config.h"
+
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <cxxabi.h>
#endif
-#include <inttypes.h>
-
#include <algorithm>
+#include <cinttypes>
#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/ext/base/string_utils.h"
@@ -43,6 +40,7 @@
#include "src/profiling/symbolizer/symbolize_database.h"
#include "src/profiling/symbolizer/symbolizer.h"
#include "src/trace_processor/containers/string_pool.h"
+#include "tools/trace_to_text/utils.h"
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
diff --git a/tools/trace_to_text/symbolize_profile.cc b/tools/trace_to_text/symbolize_profile.cc
index 4f97f58..229ce24 100644
--- a/tools/trace_to_text/symbolize_profile.cc
+++ b/tools/trace_to_text/symbolize_profile.cc
@@ -21,9 +21,10 @@
#include "perfetto/base/logging.h"
#include "perfetto/trace_processor/trace_processor.h"
+#include "src/profiling/symbolizer/breakpad_symbolizer.h"
+#include "src/profiling/symbolizer/local_symbolizer.h"
#include "src/profiling/symbolizer/symbolize_database.h"
#include "src/profiling/symbolizer/symbolizer.h"
-#include "src/profiling/symbolizer/local_symbolizer.h"
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
@@ -35,9 +36,14 @@
// 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;
+ const char* breakpad_dir = getenv("BREAKPAD_SYMBOL_DIR");
+ if (breakpad_dir == nullptr) {
+ symbolizer = profiling::LocalSymbolizerOrDie(
+ profiling::GetPerfettoBinaryPath(), getenv("PERFETTO_SYMBOLIZER_MODE"));
+ } else {
+ symbolizer.reset(new profiling::BreakpadSymbolizer(breakpad_dir));
+ }
if (!symbolizer)
PERFETTO_FATAL("No symbolizer selected");
diff --git a/tools/trace_to_text/trace_to_systrace.cc b/tools/trace_to_text/trace_to_systrace.cc
index 03d8aa0..3ed00f3 100644
--- a/tools/trace_to_text/trace_to_systrace.cc
+++ b/tools/trace_to_text/trace_to_systrace.cc
@@ -16,10 +16,10 @@
#include "tools/trace_to_text/trace_to_systrace.h"
-#include <inttypes.h>
#include <stdio.h>
#include <algorithm>
+#include <cinttypes>
#include <functional>
#include <map>
#include <memory>
@@ -49,8 +49,7 @@
const char kProcessDumpFooter[] = "\"";
-const char kSystemTraceEvents[] =
- " \"systemTraceEvents\": \"";
+const char kSystemTraceEvents[] = " \"systemTraceEvents\": \"";
const char kFtraceHeader[] =
"# tracer: nop\n"
diff --git a/tools/trace_to_text/trace_to_text.cc b/tools/trace_to_text/trace_to_text.cc
index 1199d3a..0bca321 100644
--- a/tools/trace_to_text/trace_to_text.cc
+++ b/tools/trace_to_text/trace_to_text.cc
@@ -102,7 +102,8 @@
stream.avail_out = sizeof(out);
ret = inflate(&stream, Z_NO_FLUSH);
if (ret != Z_STREAM_END && ret != Z_OK) {
- PERFETTO_ELOG("Error when decompressing packets");
+ PERFETTO_ELOG("Error when decompressing packets: %s",
+ (stream.msg ? stream.msg : ""));
return;
}
data.insert(data.end(), out, out + (sizeof(out) - stream.avail_out));
diff --git a/tools/trace_to_text/utils.cc b/tools/trace_to_text/utils.cc
index fb0505c..410e898 100644
--- a/tools/trace_to_text/utils.cc
+++ b/tools/trace_to_text/utils.cc
@@ -16,9 +16,9 @@
#include "tools/trace_to_text/utils.h"
-#include <inttypes.h>
#include <stdio.h>
+#include <cinttypes>
#include <memory>
#include <ostream>
#include <set>
diff --git a/tools/tracebox b/tools/tracebox
new file mode 100755
index 0000000..158ff73
--- /dev/null
+++ b/tools/tracebox
@@ -0,0 +1,192 @@
+#!/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 file should do the same thing when being invoked in any of these ways:
+# ./tracebox
+# python tracebox
+# bash tracebox
+# cat ./tracebox | bash
+# cat ./tracebox | python -
+
+BASH_FALLBACK = """ "
+exec python3 - "$@" <<'#'EOF
+#"""
+
+TOOL_NAME = 'tracebox'
+
+# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
+# Revision: 387c10f55b96e95f96ec9248c3af28772bccfff0
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'mac-amd64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1315792,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/mac-amd64/tracebox',
+ 'sha256':
+ '8460e9e87b41ee5011df50d1a63edd02b4f58003f1ffdd2c0e9f8dc283491e2b',
+ 'platform':
+ 'darwin',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'linux-amd64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1750688,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/linux-amd64/tracebox',
+ 'sha256':
+ '05fa0a739ce40d38cf8b65c3f43f8f509991394c69f0f17e68c3f46076904716',
+ 'platform':
+ 'linux',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'linux-amd64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1750688,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/linux-amd64/tracebox',
+ 'sha256':
+ '05fa0a739ce40d38cf8b65c3f43f8f509991394c69f0f17e68c3f46076904716',
+ 'platform':
+ 'linux',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'linux-arm',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 990096,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/linux-arm/tracebox',
+ 'sha256':
+ '4777d8034bf9cd4f2ea8ce28d62aef7facfd4cd7e22e1de415d178d287a437e5',
+ 'platform':
+ 'linux',
+ 'machine': ['armv6l', 'armv7l', 'armv8l']
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'linux-arm64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1493456,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/linux-arm64/tracebox',
+ 'sha256':
+ '799d657730e1edfc647a5ac344c3840beaf192e432faaff395ba55cacabdb01e',
+ 'platform':
+ 'linux',
+ 'machine': ['aarch64']
+}]
+
+
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ print('Downloading ' + url)
+ subprocess.check_call(['curl', '-f', '-L', '-#', '-o', tmp_path, url])
+ with open(tmp_path, 'rb') as fd:
+ actual_sha256 = hashlib.sha256(fd.read()).hexdigest()
+ if actual_sha256 != sha256:
+ raise Exception('Checksum mismatch for %s (actual: %s, expected: %s)' %
+ (url, actual_sha256, sha256))
+ os.chmod(tmp_path, 0o755)
+ os.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and entry.get(
+ 'platform') == plat and machine in entry.get('machine', []):
+ manifest_entry = entry
+ break
+ if manifest_entry is None:
+ if soft_fail:
+ return None
+ raise Exception(
+ ('No prebuilts available for %s-%s\n' % (plat, machine)) +
+ 'See https://perfetto.dev/docs/contributing/build-instructions')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
+
+
+# END_SECTION_GENERATED_BY(roll-prebuilts)
+
+if __name__ == '__main__':
+ import sys, os
+ bin_path = get_perfetto_prebuilt(TOOL_NAME)
+ os.execv(bin_path, [bin_path] + sys.argv[1:])
+
+#EOF
diff --git a/tools/traceconv b/tools/traceconv
index 9887ec1..ab2fd98 100755
--- a/tools/traceconv
+++ b/tools/traceconv
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
+# 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.
@@ -24,73 +24,137 @@
exec python3 - "$@" <<'#'EOF
#"""
-import hashlib
-import os
-import sys
-import subprocess
-import tempfile
-import platform
+TOOL_NAME = 'trace_to_text'
+
+# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
+# Revision: 387c10f55b96e95f96ec9248c3af28772bccfff0
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'mac-amd64',
+ 'file_name':
+ 'trace_to_text',
+ 'file_size':
+ 7087080,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/mac-amd64/trace_to_text',
+ 'sha256':
+ '19126f67c1edd3e525c63d3cc5085ea965d77868b91d163052f8f608cf496cd8',
+ 'platform':
+ 'darwin',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'linux-amd64',
+ 'file_name':
+ 'trace_to_text',
+ 'file_size':
+ 7437720,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/linux-amd64/trace_to_text',
+ 'sha256':
+ '8112656e058a8ebbd6f7251452527c51c0a3e88bc160a33d95e3da61228d1285',
+ 'platform':
+ 'linux',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'windows-amd64',
+ 'file_name':
+ 'trace_to_text.exe',
+ 'file_size':
+ 6703616,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/387c10f55b96e95f96ec9248c3af28772bccfff0/windows-amd64/trace_to_text.exe',
+ 'sha256':
+ 'fc776c807682c1de0785468190fe9795fda97f2a9c32dad15affe24b81dad817',
+ 'platform':
+ 'win32',
+ 'machine': ['amd64']
+}]
-TRACE_TO_TEXT_SHAS = {
- 'linux': '7e3e10dfb324e31723efd63ac25037856e06eba0',
- 'mac': '21f0f42dd019b4f09addd404a114fbf2322ca8a4',
-}
-TRACE_TO_TEXT_PATH = tempfile.gettempdir()
-TRACE_TO_TEXT_BASE_URL = ('https://storage.googleapis.com/perfetto/')
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ print('Downloading ' + url)
+ subprocess.check_call(['curl', '-f', '-L', '-#', '-o', tmp_path, url])
+ with open(tmp_path, 'rb') as fd:
+ actual_sha256 = hashlib.sha256(fd.read()).hexdigest()
+ if actual_sha256 != sha256:
+ raise Exception('Checksum mismatch for %s (actual: %s, expected: %s)' %
+ (url, actual_sha256, sha256))
+ os.chmod(tmp_path, 0o755)
+ os.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and entry.get(
+ 'platform') == plat and machine in entry.get('machine', []):
+ manifest_entry = entry
+ break
+ if manifest_entry is None:
+ if soft_fail:
+ return None
+ raise Exception(
+ ('No prebuilts available for %s-%s\n' % (plat, machine)) +
+ 'See https://perfetto.dev/docs/contributing/build-instructions')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
-def DownloadURL(url, out_file):
- subprocess.check_call(['curl', '-L', '-#', '-o', out_file, url])
-
-
-def check_hash(file_name, sha_value):
- with open(file_name, 'rb') as fd:
- file_hash = hashlib.sha1(fd.read()).hexdigest()
- return file_hash == sha_value
-
-
-def load_trace_to_text(platform):
- sha_value = TRACE_TO_TEXT_SHAS[platform]
- file_name = 'trace_to_text-' + platform + '-' + sha_value
- local_file = os.path.join(TRACE_TO_TEXT_PATH, file_name)
-
- if os.path.exists(local_file):
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- else:
- return local_file
-
- url = TRACE_TO_TEXT_BASE_URL + file_name
- DownloadURL(url, local_file)
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- raise ValueError("Invalid signature.")
- os.chmod(local_file, 0o755)
- return local_file
-
-
-def main(argv):
- os_name = None
- if sys.platform.startswith('linux'):
- os_name = 'linux'
- elif sys.platform.startswith('darwin'):
- os_name = '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)
- os.execv(trace_to_text_binary, [trace_to_text_binary] + argv[1:])
-
+# END_SECTION_GENERATED_BY(roll-prebuilts)
if __name__ == '__main__':
- sys.exit(main(sys.argv))
+ import sys, os
+ bin_path = get_perfetto_prebuilt(TOOL_NAME)
+ os.execv(bin_path, [bin_path] + sys.argv[1:])
#EOF
diff --git a/tools/update_trace_processor b/tools/update_trace_processor
deleted file mode 100755
index 4ab27f6..0000000
--- a/tools/update_trace_processor
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-
-set -e
-
-DIR=$(mktemp -d out/perfetto.XXXXXX)
-STRIPPED_DIR=$DIR/stripped
-
-function cleanup {
- rm -rf "$DIR"
- echo "Deleted temp working directory $DIR"
-}
-
-#trap cleanup EXIT
-
-function is_mac {
- ! test -d /proc
- return $?
-}
-
-tools/gn gen $DIR --args='is_clang=true is_debug=false'
-tools/ninja -C $DIR trace_processor_shell
-
-if is_mac; then
- platform=mac
-else
- platform=linux
-fi
-
-if which shasum; then
- NEW_SHA=$(shasum $STRIPPED_DIR/trace_processor_shell | cut -f1 -d' ') # Mac OS
-else
- NEW_SHA=$(sha1sum $STRIPPED_DIR/trace_processor_shell | cut -f1 -d' ') # Linux
-fi
-
-name=trace_processor_shell-$platform-$NEW_SHA
-
-gsutil cp $STRIPPED_DIR/trace_processor_shell gs://perfetto/$name
-gsutil acl ch -u AllUsers:R gs://perfetto/$name
-
-echo 'Now run the following command to update tools/trace_processor:'
-echo "sed \"s/'$platform': '[^']*',/'$platform': '$NEW_SHA',/\" --in-place tools/trace_processor"
diff --git a/tools/update_tracebox b/tools/update_tracebox
deleted file mode 100755
index 0836b25..0000000
--- a/tools/update_tracebox
+++ /dev/null
@@ -1,76 +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
-
-# cd into the repo root so all commands are independent of the cwd.
-cd -P ${BASH_SOURCE[0]%/*}/..
-
-GN_ARGS="$GN_ARGS" # Allow to expand GN_ARGS from env for ccache.
-
-set -u
-
-DIR=out/tmp_tracebox
-mkdir -p $DIR
-
-function cleanup {
- rm -rf "$DIR"
- echo "Deleted temp working directory $DIR"
-}
-
-#trap cleanup EXIT
-
-function is_mac {
- ! test -d /proc
- return $?
-}
-
-VERSION="$(tools/write_version_header.py --stdout)"
-
-# Allow overriding the build targets via the cmdline (for testing).
-if [ "$#" -gt 0 ]; then
- COMBOS="$@"
-else
- COMBOS="android-arm android-arm64 android-x86 android-x64"
-fi
-
-for COMBO in $COMBOS; do
- IFS=- read PLATFORM ARCH <<< "$COMBO"
- echo "Building for $COMBO"
- rm -rf $DIR
- mkdir -p $DIR
- GN_ARGS="$GN_ARGS is_debug=false monolithic_binaries = true"
- GN_ARGS="$GN_ARGS target_os = \"$PLATFORM\" target_cpu = \"$ARCH\""
- set -x
- tools/gn gen $DIR --args="$GN_ARGS"
- tools/ninja -C $DIR tracebox
- set +x
- BINARY=$DIR/stripped/tracebox
-if which shasum; then
- NEW_SHA=$(shasum $BINARY | cut -f1 -d' ') # Mac OS
-else
- NEW_SHA=$(sha1sum $BINARY | cut -f1 -d' ') # Linux
-fi
- FULL_NAME=tracebox-$COMBO-$NEW_SHA
-
- set -x
- gsutil cp -n -a public-read $BINARY gs://perfetto/$FULL_NAME
- sed -e \
- "s/'$COMBO': '.*/'$COMBO': '$NEW_SHA', # $VERSION/" \
- -i .tmp tools/record_android_trace
- set +x
- rm -f tools/record_android_trace.tmp
- echo ""
-done
diff --git a/tools/update_traceconv b/tools/update_traceconv
deleted file mode 100755
index 236068c..0000000
--- a/tools/update_traceconv
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-
-set -e
-
-DIR=$(mktemp -d out/perfetto.XXXXXX)
-STRIPPED_DIR=$DIR/stripped
-
-function cleanup {
- rm -rf "$DIR"
- echo "Deleted temp working directory $DIR"
-}
-
-#trap cleanup EXIT
-
-function is_mac {
- ! test -d /proc
- return $?
-}
-
-tools/gn gen $DIR --args='is_clang=true is_debug=false'
-tools/ninja -C $DIR trace_to_text
-
-if is_mac; then
- platform=mac
-else
- platform=linux
-fi
-
-if which shasum; then
- NEW_SHA=$(shasum $STRIPPED_DIR/trace_to_text | cut -f1 -d' ') # Mac OS
-else
- NEW_SHA=$(sha1sum $STRIPPED_DIR/trace_to_text | cut -f1 -d' ') # Linux
-fi
-
-name=trace_to_text-$platform-$NEW_SHA
-
-gsutil cp $STRIPPED_DIR/trace_to_text gs://perfetto/$name
-gsutil cp $STRIPPED_DIR/trace_to_text gs://chromium-telemetry/binary_dependencies/$name
-gsutil acl ch -u AllUsers:R gs://perfetto/$name
-gsutil acl ch -u AllUsers:R gs://chromium-telemetry/binary_dependencies/$name
-
-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
index dd02a69..e8ddcb9 100755
--- a/tools/write_version_header.py
+++ b/tools/write_version_header.py
@@ -20,11 +20,10 @@
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).
+The latter is concatenated to the version number to disambiguate builds made
+from release tags vs builds made from the main branch vs UI builds made from the
+ui-canary/ui-stable branch.
"""
import argparse
@@ -56,30 +55,17 @@
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."""
+def get_git_sha1(commitish):
+ """Returns the SHA1 of the provided commit-ish"""
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'],
+ commit_sha1 = subprocess.check_output(['git', 'rev-parse', commitish],
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)
+ return commit_sha1
def write_if_unchanged(path, content):
@@ -106,18 +92,17 @@
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'.
+ if args.no_git:
+ head_sha1 = SCM_REV_NOT_AVAILABLE
else:
+ head_sha1 = get_git_sha1('HEAD') # SCM_REV_NOT_AVAILABLE on failure.
+
+ if head_sha1 == SCM_REV_NOT_AVAILABLE:
version = release # e.g., 'v9.0'.
+ else:
+ sha1_abbrev = head_sha1[:9]
+ version = f'{release}-{sha1_abbrev}' # e.g., 'v9.0-adeadbeef'.
if args.cpp_out:
guard = '%s_' % args.cpp_out.upper()
@@ -129,7 +114,7 @@
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('#define PERFETTO_VERSION_SCM_REVISION() "%s"' % head_sha1)
lines.append('')
lines.append('#endif // %s' % guard)
lines.append('')
@@ -139,7 +124,7 @@
if args.ts_out:
lines = []
lines.append('export const VERSION = "%s";' % version)
- lines.append('export const SCM_REVISION = "%s";' % git_sha1)
+ lines.append('export const SCM_REVISION = "%s";' % head_sha1)
content = '\n'.join(lines)
write_if_unchanged(args.ts_out, content)
diff --git a/traced_perf.rc b/traced_perf.rc
index 692977c..1835466 100644
--- a/traced_perf.rc
+++ b/traced_perf.rc
@@ -27,7 +27,7 @@
user nobody
group nobody readproc
capabilities KILL DAC_READ_SEARCH
- writepid /dev/cpuset/foreground/tasks
+ task_profiles ProcessCapacityHigh
# Daemon run state:
# * initially off
diff --git a/ui/PRESUBMIT.py b/ui/PRESUBMIT.py
index a4d6df0..d12758a 100644
--- a/ui/PRESUBMIT.py
+++ b/ui/PRESUBMIT.py
@@ -12,13 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import print_function
+import time
import subprocess
from os.path import relpath
+def RunAndReportIfLong(func, *args, **kargs):
+ start = time.time()
+ results = func(*args, **kargs)
+ end = time.time()
+ limit = 0.5 # seconds
+ name = func.__name__
+ runtime = end - start
+ if runtime > limit:
+ print("{} took >{:.2}s ({:.2}s)".format(name, limit, runtime))
+ return results
+
+
def CheckChange(input, output):
results = []
- results += CheckTslint(input, output)
+ results += RunAndReportIfLong(CheckTslint, input, output)
return results
diff --git a/ui/build.js b/ui/build.js
index 28f0456..e9d6c60 100644
--- a/ui/build.js
+++ b/ui/build.js
@@ -58,9 +58,9 @@
// +----------------------+ | +----------+ +---------+ +--------------------+|
// | src/assets/*.png | | | assets/ | |*.wasm.js| | frontend_bundle.js ||
// +----------------------+ | | *.css | |*.wasm | +--------------------+|
-// | buildtools/typefaces |-->| | *.png | +---------+ |controller_bundle.js||
+// | buildtools/typefaces |-->| | *.png | +---------+ | engine_bundle.js ||
// +----------------------+ | | *.woff2 | +--------------------+|
-// | buildtools/legacy_tv | | | tv.html | | engine_bundle.js ||
+// | buildtools/legacy_tv | | | tv.html | |traceconv_bundle.js ||
// +----------------------+ | +----------+ +--------------------+|
// +------------------------------------------------+
@@ -75,6 +75,7 @@
const ROOT_DIR = path.dirname(__dirname); // The repo root.
const VERSION_SCRIPT = pjoin(ROOT_DIR, 'tools/write_version_header.py');
+const GEN_IMPORTS_SCRIPT = pjoin(ROOT_DIR, 'tools/gen_ui_imports');
const cfg = {
watch: false,
@@ -82,7 +83,6 @@
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:
@@ -117,12 +117,11 @@
let tasks = [];
let tasksTot = 0, tasksRan = 0;
-let serverStarted = false;
let httpWatches = [];
let tStart = Date.now();
let subprocesses = [];
-function main() {
+async function main() {
const parser = new argparse.ArgumentParser();
parser.addArgument('--out', {help: 'Output directory'});
parser.addArgument(['--watch', '-w'], {action: 'storeTrue'});
@@ -130,8 +129,11 @@
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(['--run-unittests', '-t'], {action: 'storeTrue'});
+ parser.addArgument(['--run-integrationtests', '-T'], {action: 'storeTrue'});
parser.addArgument(['--debug', '-d'], {action: 'storeTrue'});
+ parser.addArgument(['--interactive', '-i'], {action: 'storeTrue'});
+ parser.addArgument(['--rebaseline', '-r'], {action: 'storeTrue'});
const args = parser.parseArgs();
const clean = !args.no_build;
@@ -148,6 +150,12 @@
cfg.verbose = !!args.verbose;
cfg.debug = !!args.debug;
cfg.startHttpServer = args.serve;
+ if (args.interactive) {
+ process.env.PERFETTO_UI_TESTS_INTERACTIVE = '1';
+ }
+ if (args.rebaseline) {
+ process.env.PERFETTO_UI_TESTS_REBASELINE = '1';
+ }
process.on('SIGINT', () => {
console.log('\nSIGINT received. Killing all child processes and exiting');
@@ -179,6 +187,7 @@
scanDir('ui/src/chrome_extension');
scanDir('buildtools/typefaces');
scanDir('buildtools/catapult_trace_viewer');
+ generateImports('ui/src/tracks', 'all_tracks.ts');
compileProtos();
genVersion();
transpileTsProject('ui');
@@ -192,8 +201,25 @@
scanDir(cfg.outDistRootDir);
}
- if (args.run_tests) {
- runTests();
+
+ // We should enter the loop only in watch mode, where tsc and rollup are
+ // asynchronous because they run in watch mode.
+ const tStart = Date.now();
+ while (!isDistComplete()) {
+ const secs = Math.ceil((Date.now() - tStart) / 1000);
+ process.stdout.write(`Waiting for first build to complete... ${secs} s\r`);
+ await new Promise(r => setTimeout(r, 500));
+ }
+ if (cfg.watch) console.log('\nFirst build completed!');
+
+ if (cfg.startHttpServer) {
+ startServer();
+ }
+ if (args.run_unittests) {
+ runTests('jest.unittest.config.js');
+ }
+ if (args.run_integrationtests) {
+ runTests('jest.integrationtest.config.js');
}
}
@@ -201,12 +227,17 @@
// 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));
- }
+function runTests(cfgFile) {
+ const args = [
+ '--rootDir',
+ cfg.outTscDir,
+ '--verbose',
+ '--runInBand',
+ '--detectOpenHandles',
+ '--forceExit',
+ '--projects',
+ pjoin(ROOT_DIR, 'ui/config', cfgFile)
+ ];
if (cfg.watch) {
args.push('--watchAll');
addTask(execNode, ['jest', args, {async: true}]);
@@ -275,6 +306,19 @@
addTask(execNode, ['pbts', pbtsArgs]);
}
+function generateImports(dir, name) {
+ // We have to use the symlink (ui/src/gen) rather than cfg.outGenDir
+ // below since we want to generate the correct relative imports. For example:
+ // ui/src/frontend/foo.ts
+ // import '../gen/all_plugins.ts';
+ // ui/src/gen/all_plugins.ts (aka ui/out/tsc/gen/all_plugins.ts)
+ // import '../frontend/some_plugin.ts';
+ const dstTs = pjoin(ROOT_DIR, 'ui/src/gen', name);
+ const inputDir = pjoin(ROOT_DIR, dir);
+ const args = [GEN_IMPORTS_SCRIPT, inputDir, '--out', dstTs];
+ addTask(exec, ['python3', args]);
+}
+
// Generates a .ts source that defines the VERSION and SCM_REVISION constants.
function genVersion() {
const cmd = 'python3';
@@ -284,8 +328,14 @@
}
function updateSymlinks() {
+ // /ui/out -> /out/ui.
mklink(cfg.outUiDir, pjoin(ROOT_DIR, 'ui/out'));
+ // /out/ui/test/data -> /test/data (For UI tests).
+ mklink(
+ pjoin(ROOT_DIR, 'test/data'),
+ pjoin(ensureDir(pjoin(cfg.outDir, 'test')), 'data'));
+
// 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(
@@ -397,7 +447,14 @@
return;
}
- const absPath = path.normalize(path.join(cfg.outDistRootDir, uri));
+ let absPath = path.normalize(path.join(cfg.outDistRootDir, uri));
+ // We want to be able to use the data in '/test/' for e2e tests.
+ // However, we don't want do create a symlink into the 'dist/' dir,
+ // because 'dist/' gets shipped on the production server.
+ if (uri.startsWith('/test/')) {
+ absPath = pjoin(ROOT_DIR, uri);
+ }
+
fs.readFile(absPath, function(err, data) {
if (err) {
res.writeHead(404);
@@ -427,6 +484,24 @@
.listen(port, '127.0.0.1');
}
+function isDistComplete() {
+ const requiredArtifacts = [
+ 'frontend_bundle.js',
+ 'engine_bundle.js',
+ 'traceconv_bundle.js',
+ 'trace_processor.wasm',
+ 'perfetto.css',
+ ];
+ const relPaths = new Set();
+ walk(cfg.outDistDir, absPath => {
+ relPaths.add(path.relative(cfg.outDistDir, absPath));
+ });
+ for (const fName of requiredArtifacts) {
+ if (!relPaths.has(fName)) return false;
+ }
+ return true;
+}
+
// 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) {
@@ -476,11 +551,6 @@
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|.
diff --git a/ui/config/.gitignore b/ui/config/.gitignore
new file mode 100644
index 0000000..acd163c
--- /dev/null
+++ b/ui/config/.gitignore
@@ -0,0 +1 @@
+/jest.individual.unit.config.js
diff --git a/ui/config/headless_environment.js b/ui/config/headless_environment.js
deleted file mode 100644
index 6c4f3ec..0000000
--- a/ui/config/headless_environment.js
+++ /dev/null
@@ -1,36 +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.
-
-const NodeEnvironment = require('jest-environment-node');
-const puppeteer = require('puppeteer');
-
-module.exports = class HeadlessEnvironment extends NodeEnvironment {
- constructor(config) {
- super(config);
- }
-
- async setup() {
- await super.setup();
- this.global.__BROWSER__ = await puppeteer.launch();
- }
-
- async teardown() {
- await this.global.__BROWSER__.close();
- await super.teardown();
- }
-
- runScript(script) {
- return super.runScript(script);
- }
-}
diff --git a/ui/config/headless_teardown.js b/ui/config/headless_teardown.js
deleted file mode 100644
index 5fb4f1a..0000000
--- a/ui/config/headless_teardown.js
+++ /dev/null
@@ -1,17 +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.
-
-module.exports = async function() {
- console.log("End!");
-}
diff --git a/ui/config/integrationtest_env.js b/ui/config/integrationtest_env.js
new file mode 100644
index 0000000..b7509ee
--- /dev/null
+++ b/ui/config/integrationtest_env.js
@@ -0,0 +1,65 @@
+// 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 NodeEnvironment = require('jest-environment-node');
+const puppeteer = require('puppeteer');
+
+module.exports = class IntegrationtestEnvironment extends NodeEnvironment {
+ constructor(config) {
+ super(config);
+ }
+
+ async setup() {
+ await super.setup();
+ const headless = process.env.PERFETTO_UI_TESTS_INTERACTIVE !== '1';
+ if (headless) {
+ console.log('Starting Perfetto UI tests in headless mode.');
+ console.log(
+ 'Pass --interactive to run-integrationtests or set ' +
+ 'PERFETTO_UI_TESTS_INTERACTIVE=1 to inspect the behavior ' +
+ 'in a visible Chrome window');
+ }
+ this.global.__BROWSER__ = await puppeteer.launch({
+ args: [
+ '--window-size=1920,1080',
+ '--disable-accelerated-2d-canvas',
+ '--disable-gpu',
+ '--no-sandbox', // Disable sandbox to run in Docker.
+ '--disable-setuid-sandbox',
+ '--font-render-hinting=none',
+ '--enable-benchmarking', // Disable finch and other sources of non
+ // determinism.
+ ],
+
+ // This is so screenshot in --interactive and headles mode match. The
+ // scrollbars are never part of the screenshot, but without this cmdline
+ // switch, in headless mode we don't get any blank space (as if it was
+ // overflow:hidden) and that changes the layout of the page.
+ ignoreDefaultArgs: ['--hide-scrollbars'],
+
+ headless: headless,
+ });
+ }
+
+ async teardown() {
+ if (this.global.__BROWSER__) {
+ await this.global.__BROWSER__.close();
+ }
+ await super.teardown();
+ }
+
+ runScript(script) {
+ return super.runScript(script);
+ }
+}
diff --git a/ui/config/integrationtest_setup.js b/ui/config/integrationtest_setup.js
new file mode 100644
index 0000000..e4cd7e8
--- /dev/null
+++ b/ui/config/integrationtest_setup.js
@@ -0,0 +1,57 @@
+// 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');
+const http = require('http');
+const child_process = require('child_process');
+
+module.exports = async function() {
+ // Start the local HTTP server.
+ const ROOT_DIR = path.dirname(path.dirname(__dirname));
+ const node = path.join(ROOT_DIR, 'ui', 'node');
+ const args = [
+ path.join(ROOT_DIR, 'ui', 'build.js'),
+ '--serve',
+ '--no-build',
+ '--out=.'
+ ];
+ const spwOpts = {stdio: ['ignore', 'inherit', 'inherit']};
+ const srvProc = child_process.spawn(node, args, spwOpts);
+ global.__DEV_SERVER__ = srvProc;
+
+ // Wait for the HTTP server to be ready.
+ let attempts = 10;
+ for (; attempts > 0; attempts--) {
+ await new Promise(r => setTimeout(r, 1000));
+ try {
+ await new Promise((resolve, reject) => {
+ const req = http.request('http://127.0.0.1:10000/frontend_bundle.js');
+ req.end();
+ req.on('error', err => reject(err));
+ req.on('finish', () => resolve());
+ });
+ break;
+ } catch (err) {
+ console.error('Waiting for HTTP server to come up', err.message);
+ continue;
+ }
+ }
+ if (attempts == 0) {
+ throw new Error('HTTP server didn\'t come up');
+ }
+ if (srvProc.exitCode !== null) {
+ throw new Error(
+ `The dev server unexpectedly exited, code=${srvProc.exitCode}`);
+ }
+}
diff --git a/ui/config/jest.individual.unit.config.js b/ui/config/integrationtest_teardown.js
similarity index 67%
copy from ui/config/jest.individual.unit.config.js
copy to ui/config/integrationtest_teardown.js
index 7d9d2f5..6d152dd 100644
--- a/ui/config/jest.individual.unit.config.js
+++ b/ui/config/integrationtest_teardown.js
@@ -12,11 +12,13 @@
// 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'},
+module.exports = async function() {
+ const proc = global.__DEV_SERVER__;
+ // Kill the HTTP server.
+ proc.kill();
+ for (;;) {
+ if (proc.exitCode !== null || proc.killed) break;
+ console.log('Waiting for dev server termination');
+ await new Promise(r => setTimeout(r, 1000));
+ }
}
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.integrationtest.config.js
similarity index 72%
rename from ui/config/jest.individual.unit.config.js
rename to ui/config/jest.integrationtest.config.js
index 7d9d2f5..079abaf 100644
--- a/ui/config/jest.individual.unit.config.js
+++ b/ui/config/jest.integrationtest.config.js
@@ -12,11 +12,10 @@
// 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'},
+ transform: {},
+ testRegex: '.*_integrationtest.js$',
+ globalSetup: __dirname + '/integrationtest_setup.js',
+ globalTeardown: __dirname + '/integrationtest_teardown.js',
+ testEnvironment: __dirname + '/integrationtest_env.js',
}
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/jest.jsdom.config.js b/ui/config/jest.unittest.config.js
similarity index 93%
rename from ui/config/jest.jsdom.config.js
rename to ui/config/jest.unittest.config.js
index dd07d83..fc1bd35 100644
--- a/ui/config/jest.jsdom.config.js
+++ b/ui/config/jest.unittest.config.js
@@ -14,6 +14,6 @@
module.exports = {
transform: {},
- testRegex: '_jsdomtest.js$',
+ testRegex: '_(unittest|jsdomtest)[.]js$',
testEnvironment: 'jsdom'
}
diff --git a/ui/config/rollup.config.js b/ui/config/rollup.config.js
index 380aa91..42f5afe 100644
--- a/ui/config/rollup.config.js
+++ b/ui/config/rollup.config.js
@@ -48,12 +48,20 @@
'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;'}]
+ patterns: [
+ // Protobufjs's inquire() uses eval but that's not really needed in
+ // the browser. https://github.com/protobufjs/protobuf.js/issues/593
+ {test: /eval\(.*\(moduleName\);/g, replace: 'undefined;'},
+
+ // Immer entry point has a if (process.env.NODE_ENV === 'production')
+ // but |process| is not defined in the browser. Bypass.
+ // https://github.com/immerjs/immer/issues/557
+ {test: /process\.env\.NODE_ENV/g, replace: '\'production\''},
+ ]
}),
+
// Translate source maps to point back to the .ts sources.
sourcemaps(),
],
@@ -86,6 +94,7 @@
defBundle('frontend', 'dist_version'),
defBundle('controller', 'dist_version'),
defBundle('engine', 'dist_version'),
+ defBundle('traceconv', 'dist_version'),
defBundle('chrome_extension', 'chrome_extension'),
defServiceWorkerBundle(),
]
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 70441b8..dba56b4d 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -13,35 +13,35 @@
"@babel/highlight": "^7.12.13"
}
},
+ "@babel/compat-data": {
+ "version": "7.14.4",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.4.tgz",
+ "integrity": "sha512-i2wXrWQNkH6JplJQGn3Rd2I4Pij8GdHkXwHMxm+zV5YG/Jci+bCNrWZEWC4o+umiDkRrRs4dVzH3X4GP7vyjQQ==",
+ "dev": true
+ },
"@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.14.3",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.3.tgz",
+ "integrity": "sha512-jB5AmTKOCSJIZ72sd78ECEhuPiDMKlQdDI/4QRI6lzYATx5SSogS1oQA2AoPecRCknm30gHi2l+QVvNUu3wZAg==",
"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/generator": "^7.14.3",
+ "@babel/helper-compilation-targets": "^7.13.16",
+ "@babel/helper-module-transforms": "^7.14.2",
+ "@babel/helpers": "^7.14.0",
+ "@babel/parser": "^7.14.3",
"@babel/template": "^7.12.13",
- "@babel/traverse": "^7.12.13",
- "@babel/types": "^7.12.13",
+ "@babel/traverse": "^7.14.2",
+ "@babel/types": "^7.14.2",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
- "gensync": "^1.0.0-beta.1",
+ "gensync": "^1.0.0-beta.2",
"json5": "^2.1.2",
- "lodash": "^4.17.19",
- "semver": "^5.4.1",
+ "semver": "^6.3.0",
"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==",
- "dev": true
- },
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -51,12 +51,12 @@
}
},
"@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.14.3",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz",
+ "integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.13",
+ "@babel/types": "^7.14.2",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
},
@@ -69,15 +69,27 @@
}
}
},
+ "@babel/helper-compilation-targets": {
+ "version": "7.14.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.4.tgz",
+ "integrity": "sha512-JgdzOYZ/qGaKTVkn5qEDV/SXAh8KcyUVkCoSWGN8T3bwrgd6m+/dJa2kVGi6RJYJgEYPBdZ84BZp9dUjNWkBaA==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.14.4",
+ "@babel/helper-validator-option": "^7.12.17",
+ "browserslist": "^4.16.6",
+ "semver": "^6.3.0"
+ }
+ },
"@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.14.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz",
+ "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==",
"dev": true,
"requires": {
"@babel/helper-get-function-arity": "^7.12.13",
"@babel/template": "^7.12.13",
- "@babel/types": "^7.12.13"
+ "@babel/types": "^7.14.2"
}
},
"@babel/helper-get-function-arity": {
@@ -90,38 +102,45 @@
}
},
"@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.13.12",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz",
+ "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.13"
+ "@babel/types": "^7.13.12"
}
},
"@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.13.12",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz",
+ "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.13"
+ "@babel/types": "^7.13.12"
}
},
"@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.14.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.2.tgz",
+ "integrity": "sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA==",
"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-module-imports": "^7.13.12",
+ "@babel/helper-replace-supers": "^7.13.12",
+ "@babel/helper-simple-access": "^7.13.12",
"@babel/helper-split-export-declaration": "^7.12.13",
- "@babel/helper-validator-identifier": "^7.12.11",
+ "@babel/helper-validator-identifier": "^7.14.0",
"@babel/template": "^7.12.13",
- "@babel/traverse": "^7.12.13",
- "@babel/types": "^7.12.13",
- "lodash": "^4.17.19"
+ "@babel/traverse": "^7.14.2",
+ "@babel/types": "^7.14.2"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
+ "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
+ "dev": true
+ }
}
},
"@babel/helper-optimise-call-expression": {
@@ -134,30 +153,30 @@
}
},
"@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.13.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz",
+ "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==",
"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.14.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.4.tgz",
+ "integrity": "sha512-zZ7uHCWlxfEAAOVDYQpEf/uyi1dmeC7fX4nCf2iz9drnCwi1zvwXL3HwWWNXUQEJ1k23yVn3VbddiI9iJEXaTQ==",
"dev": true,
"requires": {
- "@babel/helper-member-expression-to-functions": "^7.12.13",
+ "@babel/helper-member-expression-to-functions": "^7.13.12",
"@babel/helper-optimise-call-expression": "^7.12.13",
- "@babel/traverse": "^7.12.13",
- "@babel/types": "^7.12.13"
+ "@babel/traverse": "^7.14.2",
+ "@babel/types": "^7.14.4"
}
},
"@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.13.12",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz",
+ "integrity": "sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.13"
+ "@babel/types": "^7.13.12"
}
},
"@babel/helper-split-export-declaration": {
@@ -175,15 +194,21 @@
"integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
"dev": true
},
+ "@babel/helper-validator-option": {
+ "version": "7.12.17",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz",
+ "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==",
+ "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.14.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.0.tgz",
+ "integrity": "sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg==",
"dev": true,
"requires": {
"@babel/template": "^7.12.13",
- "@babel/traverse": "^7.12.13",
- "@babel/types": "^7.12.13"
+ "@babel/traverse": "^7.14.0",
+ "@babel/types": "^7.14.0"
}
},
"@babel/highlight": {
@@ -250,9 +275,9 @@
}
},
"@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.14.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.4.tgz",
+ "integrity": "sha512-ArliyUsWDUqEGfWcmzpGUzNfLxTdTp6WU4IuP6QFSp9gGfWS6boxFCkJSJ/L4+RG8z/FnIU3WxCk6hPL9SSWeA==",
"dev": true
},
"@babel/plugin-syntax-async-generators": {
@@ -354,6 +379,15 @@
"@babel/helper-plugin-utils": "^7.8.0"
}
},
+ "@babel/plugin-syntax-top-level-await": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz",
+ "integrity": "sha512-A81F9pDwyS7yM//KwbCSDqy3Uj4NMIurtplxphWxoYtNPov7cJsDkAFNNyVlIZ3jwGycVsurZ+LtOA8gZ376iQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ }
+ },
"@babel/template": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz",
@@ -366,31 +400,37 @@
}
},
"@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.14.2",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz",
+ "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",
- "@babel/generator": "^7.12.13",
- "@babel/helper-function-name": "^7.12.13",
+ "@babel/generator": "^7.14.2",
+ "@babel/helper-function-name": "^7.14.2",
"@babel/helper-split-export-declaration": "^7.12.13",
- "@babel/parser": "^7.12.13",
- "@babel/types": "^7.12.13",
+ "@babel/parser": "^7.14.2",
+ "@babel/types": "^7.14.2",
"debug": "^4.1.0",
- "globals": "^11.1.0",
- "lodash": "^4.17.19"
+ "globals": "^11.1.0"
}
},
"@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.14.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.4.tgz",
+ "integrity": "sha512-lCj4aIs0xUefJFQnwwQv2Bxg7Omd6bgquZ6LGC+gGMh6/s5qDVfjuCMlDmYQ15SLsWHd9n+X3E75lKIhl5Lkiw==",
"dev": true,
"requires": {
- "@babel/helper-validator-identifier": "^7.12.11",
- "lodash": "^4.17.19",
+ "@babel/helper-validator-identifier": "^7.14.0",
"to-fast-properties": "^2.0.0"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
+ "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
+ "dev": true
+ }
}
},
"@bcoe/v8-coverage": {
@@ -423,132 +463,135 @@
}
},
"@istanbuljs/schema": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz",
- "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==",
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
"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.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz",
+ "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==",
"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.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^26.6.2",
+ "jest-util": "^26.6.2",
"slash": "^3.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.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz",
+ "integrity": "sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==",
"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.6.2",
+ "@jest/reporters": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
"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.6.2",
+ "jest-config": "^26.6.3",
+ "jest-haste-map": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-resolve": "^26.6.2",
+ "jest-resolve-dependencies": "^26.6.3",
+ "jest-runner": "^26.6.3",
+ "jest-runtime": "^26.6.3",
+ "jest-snapshot": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
+ "jest-watcher": "^26.6.2",
"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"
}
},
"@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.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz",
+ "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==",
"dev": true,
"requires": {
- "@jest/fake-timers": "^25.5.0",
- "@jest/types": "^25.5.0",
- "jest-mock": "^25.5.0"
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "jest-mock": "^26.6.2"
}
},
"@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.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz",
+ "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==",
"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.6.2",
+ "@sinonjs/fake-timers": "^6.0.1",
+ "@types/node": "*",
+ "jest-message-util": "^26.6.2",
+ "jest-mock": "^26.6.2",
+ "jest-util": "^26.6.2"
}
},
"@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.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz",
+ "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==",
"dev": true,
"requires": {
- "@jest/environment": "^25.5.0",
- "@jest/types": "^25.5.0",
- "expect": "^25.5.0"
+ "@jest/environment": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "expect": "^26.6.2"
}
},
"@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.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz",
+ "integrity": "sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==",
"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.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "chalk": "^4.0.0",
"collect-v8-coverage": "^1.0.0",
"exit": "^0.1.2",
"glob": "^7.1.2",
"graceful-fs": "^4.2.4",
"istanbul-lib-coverage": "^3.0.0",
- "istanbul-lib-instrument": "^4.0.0",
+ "istanbul-lib-instrument": "^4.0.3",
"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.6.2",
+ "jest-resolve": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-worker": "^26.6.2",
+ "node-notifier": "^8.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"
+ "v8-to-istanbul": "^7.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.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz",
+ "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==",
"dev": true,
"requires": {
"callsites": "^3.0.0",
@@ -557,64 +600,64 @@
}
},
"@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.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz",
+ "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==",
"dev": true,
"requires": {
- "@jest/console": "^25.5.0",
- "@jest/types": "^25.5.0",
+ "@jest/console": "^26.6.2",
+ "@jest/types": "^26.6.2",
"@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.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz",
+ "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==",
"dev": true,
"requires": {
- "@jest/test-result": "^25.5.0",
+ "@jest/test-result": "^26.6.2",
"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.6.2",
+ "jest-runner": "^26.6.3",
+ "jest-runtime": "^26.6.3"
}
},
"@jest/transform": {
- "version": "25.5.1",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.5.1.tgz",
- "integrity": "sha512-Y8CEoVwXb4QwA6Y/9uDkn0Xfz0finGkieuV0xkdF9UtZGJeLukD5nLkaVrVsODB1ojRWlaoD0AJZpVHCSnJEvg==",
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz",
+ "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==",
"dev": true,
"requires": {
"@babel/core": "^7.1.0",
- "@jest/types": "^25.5.0",
+ "@jest/types": "^26.6.2",
"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.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-util": "^26.6.2",
"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"
}
},
"@jest/types": {
- "version": "25.5.0",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz",
- "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==",
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz",
+ "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==",
"dev": true,
"requires": {
"@types/istanbul-lib-coverage": "^2.0.0",
- "@types/istanbul-reports": "^1.1.1",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
"@types/yargs": "^15.0.0",
- "chalk": "^3.0.0"
+ "chalk": "^4.0.0"
}
},
"@protobufjs/aspromise": {
@@ -713,23 +756,38 @@
}
},
"@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.3",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
+ "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==",
"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"
+ }
+ },
+ "@tootallnate/once": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+ "dev": true
+ },
"@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.14",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz",
+ "integrity": "sha512-zGZJzzBUVDo/eV6KgbE0f0ZI7dInEYvo12Rb70uNQDshC3SkRMb67ja0GgRHZgAX3Za6rhaWlvbDO8rrGyAb1g==",
"dev": true,
"requires": {
"@babel/parser": "^7.1.0",
@@ -759,9 +817,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.11.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.1.tgz",
+ "integrity": "sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw==",
"dev": true,
"requires": {
"@babel/types": "^7.3.0"
@@ -808,9 +866,9 @@
"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.5",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
+ "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==",
"dev": true,
"requires": {
"@types/node": "*"
@@ -832,20 +890,23 @@
}
},
"@types/istanbul-reports": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz",
- "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz",
+ "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==",
"dev": true,
"requires": {
- "@types/istanbul-lib-coverage": "*",
"@types/istanbul-lib-report": "*"
}
},
"@types/jest": {
- "version": "22.2.3",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-22.2.3.tgz",
- "integrity": "sha512-e74sM9W/4qqWB6D4TWV9FQk0WoHtX1X4FJpbjxucMSVJHtFjbQOH3H6yp+xno4br0AKG0wz/kPtaN599GUOvAg==",
- "dev": true
+ "version": "26.0.23",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.23.tgz",
+ "integrity": "sha512-ZHLmWMJ9jJ9PTiT58juykZpL7KjwJywFN3Rr2pTSkyQfydf/rk22yS7W8p5DaVUMQ2BQC7oYiU3FjbTM/mYrOA==",
+ "dev": true,
+ "requires": {
+ "jest-diff": "^26.0.0",
+ "pretty-format": "^26.0.0"
+ }
},
"@types/long": {
"version": "4.0.1",
@@ -873,16 +934,25 @@
"resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.1.tgz",
"integrity": "sha512-GdZbRSJ3Cv5fiwT6I0SQ3ckeN2PWNqxd26W9Z2fCK1tGrrasGy4puvNFtnddqH9UJFMQYXxEuuB7B8UK+LLwSg=="
},
+ "@types/pixelmatch": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/pixelmatch/-/pixelmatch-5.2.3.tgz",
+ "integrity": "sha512-p+nAQVYK/DUx7+s1Xyu9dqAg0gobf7VmJ+iDA4lljg1o4XRgQHr7R2h1NwFt3gdNOZiftxWB11+0TuZqXYf19w==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
"@types/prettier": {
- "version": "1.19.1",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.1.tgz",
- "integrity": "sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==",
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.2.3.tgz",
+ "integrity": "sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA==",
"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": "5.4.3",
+ "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-5.4.3.tgz",
+ "integrity": "sha512-3nE8YgR9DIsgttLW+eJf6mnXxq8Ge+27m5SU3knWmrlfl6+KOG0Bf9f7Ua7K+C4BnaTMAh3/UpySqdAYvrsvjg==",
"dev": true,
"requires": {
"@types/node": "*"
@@ -898,9 +968,9 @@
}
},
"@types/stack-utils": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
- "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz",
+ "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==",
"dev": true
},
"@types/uuid": {
@@ -928,6 +998,16 @@
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==",
"dev": true
},
+ "@types/yauzl": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
+ "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
"abab": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
@@ -941,42 +1021,42 @@
"dev": true
},
"acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
- "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.3.0.tgz",
+ "integrity": "sha512-tqPKHZ5CaBJw0Xmy0ZZvLs1qTV+BNFSyvn77ASXkpBNfIRk8ev26fKrD9iLGwGA9zedPao52GSHzq8lyZG0NUw==",
"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"
+ "acorn": "^7.1.1",
+ "acorn-walk": "^7.1.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==",
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
"dev": true
}
}
},
"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.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
+ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
"dev": true
},
"agent-base": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
- "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"dev": true,
"requires": {
- "es6-promisify": "^5.0.0"
+ "debug": "4"
}
},
"ajv": {
@@ -998,18 +1078,18 @@
"dev": true
},
"ansi-escapes": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz",
- "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==",
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
"dev": true,
"requires": {
- "type-fest": "^0.11.0"
+ "type-fest": "^0.21.3"
},
"dependencies": {
"type-fest": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz",
- "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==",
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
"dev": true
}
}
@@ -1030,9 +1110,9 @@
}
},
"anymatch": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
- "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
@@ -1082,12 +1162,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,24 +1200,12 @@
"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",
"integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
"dev": true
},
- "async-limiter": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
- "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
- "dev": true
- },
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -1177,17 +1239,17 @@
"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.6.3",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz",
+ "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==",
"dev": true,
"requires": {
- "@jest/transform": "^25.5.1",
- "@jest/types": "^25.5.0",
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
"@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.6.2",
+ "chalk": "^4.0.0",
"graceful-fs": "^4.2.4",
"slash": "^3.0.0"
}
@@ -1206,20 +1268,21 @@
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz",
+ "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==",
"dev": true,
"requires": {
"@babel/template": "^7.3.3",
"@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.0.0",
"@types/babel__traverse": "^7.0.6"
}
},
"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": "1.0.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
+ "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
"dev": true,
"requires": {
"@babel/plugin-syntax-async-generators": "^7.8.4",
@@ -1232,17 +1295,18 @@
"@babel/plugin-syntax-numeric-separator": "^7.8.3",
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-top-level-await": "^7.8.3"
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz",
+ "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==",
"dev": true,
"requires": {
- "babel-plugin-jest-hoist": "^25.5.0",
- "babel-preset-current-node-syntax": "^0.1.2"
+ "babel-plugin-jest-hoist": "^26.6.2",
+ "babel-preset-current-node-syntax": "^1.0.0"
}
},
"balanced-match": {
@@ -1306,6 +1370,12 @@
}
}
},
+ "base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true
+ },
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
@@ -1315,6 +1385,30 @@
"tweetnacl": "^0.14.3"
}
},
+ "bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dev": true,
+ "requires": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
"block-stream": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@@ -1349,30 +1443,17 @@
"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==",
+ "browserslist": {
+ "version": "4.16.6",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
+ "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
"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"
+ "caniuse-lite": "^1.0.30001219",
+ "colorette": "^1.2.2",
+ "electron-to-chromium": "^1.3.723",
+ "escalade": "^3.1.1",
+ "node-releases": "^1.1.71"
}
},
"bser": {
@@ -1384,6 +1465,16 @@
"node-int64": "^0.4.0"
}
},
+ "buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
@@ -1458,6 +1549,12 @@
}
}
},
+ "caniuse-lite": {
+ "version": "1.0.30001233",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001233.tgz",
+ "integrity": "sha512-BmkbxLfStqiPA7IEzQpIk0UFZFf3A4E6fzjPJ6OR+bFC2L8ES9J8zGA/asoi47p8XDVkev+WJo2I2Nc8c/34Yg==",
+ "dev": true
+ },
"capture-exit": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",
@@ -1474,21 +1571,39 @@
"dev": true
},
"chalk": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
- "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
+ "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.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==",
+ "dev": true
+ },
"ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
"integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
"dev": true
},
+ "cjs-module-lexer": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz",
+ "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==",
+ "dev": true
+ },
"class-utils": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
@@ -1564,6 +1679,12 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
+ "colorette": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
+ "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
+ "dev": true
+ },
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -1597,18 +1718,6 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
- "concat-stream": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
- "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
- "dev": true,
- "requires": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^2.2.2",
- "typedarray": "^0.0.6"
- }
- },
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -1662,15 +1771,6 @@
"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"
- }
}
}
},
@@ -1719,14 +1819,14 @@
}
},
"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": {
@@ -1744,6 +1844,12 @@
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true
},
+ "decimal.js": {
+ "version": "10.2.1",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz",
+ "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==",
+ "dev": true
+ },
"decode-uri-component": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
@@ -1847,9 +1953,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.6.2",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz",
+ "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==",
"dev": true
},
"dingusjs": {
@@ -1859,12 +1965,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": {
@@ -1877,6 +1991,18 @@
"safer-buffer": "^2.1.0"
}
},
+ "electron-to-chromium": {
+ "version": "1.3.747",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.747.tgz",
+ "integrity": "sha512-+K1vnBc08GNYxCWwdRe9o3Ml30DhsNyK/qIl/NE1Dic+qCy9ZREcqGNiV4jiLiAdALK1DUG3pakJHGkJUd9QQw==",
+ "dev": true
+ },
+ "emittery": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz",
+ "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==",
+ "dev": true
+ },
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -1932,21 +2058,12 @@
"is-symbol": "^1.0.2"
}
},
- "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==",
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true
},
- "es6-promisify": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
- "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
- "dev": true,
- "requires": {
- "es6-promise": "^4.0.3"
- }
- },
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -1954,13 +2071,13 @@
"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": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz",
+ "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==",
"dev": true,
"requires": {
"esprima": "^4.0.1",
- "estraverse": "^4.2.0",
+ "estraverse": "^5.2.0",
"esutils": "^2.0.2",
"optionator": "^0.8.1",
"source-map": "~0.6.1"
@@ -1973,9 +2090,9 @@
"dev": true
},
"estraverse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
- "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+ "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
"dev": true
},
"estree-walker": {
@@ -1996,9 +2113,9 @@
"integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg=="
},
"exec-sh": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz",
- "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==",
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz",
+ "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==",
"dev": true
},
"execa": {
@@ -2073,17 +2190,17 @@
}
},
"expect": {
- "version": "25.5.0",
- "resolved": "https://registry.npmjs.org/expect/-/expect-25.5.0.tgz",
- "integrity": "sha512-w7KAXo0+6qqZZhovCaBVPSIqQp7/UTcx4M9uKt2m6pd2VB1voyC8JizLRqeEqud3AAVP02g+hbErDu5gu64tlA==",
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz",
+ "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==",
"dev": true,
"requires": {
- "@jest/types": "^25.5.0",
+ "@jest/types": "^26.6.2",
"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.3.0",
+ "jest-matcher-utils": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-regex-util": "^26.0.0"
}
},
"extend": {
@@ -2179,31 +2296,25 @@
}
},
"extract-zip": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
- "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"dev": true,
"requires": {
- "concat-stream": "^1.6.2",
- "debug": "^2.6.9",
- "mkdirp": "^0.5.4",
+ "@types/yauzl": "^2.9.1",
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
"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==",
+ "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==",
"dev": true,
"requires": {
- "ms": "2.0.0"
+ "pump": "^3.0.0"
}
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
}
}
},
@@ -2305,6 +2416,12 @@
"map-cache": "^0.2.2"
}
},
+ "fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "dev": true
+ },
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -2632,12 +2749,12 @@
"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": {
@@ -2646,6 +2763,17 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
+ "http-proxy-agent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+ "dev": true,
+ "requires": {
+ "@tootallnate/once": "1",
+ "agent-base": "6",
+ "debug": "4"
+ }
+ },
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@@ -2658,24 +2786,13 @@
}
},
"https-proxy-agent": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
- "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
"dev": true,
"requires": {
- "agent-base": "^4.3.0",
- "debug": "^3.1.0"
- },
- "dependencies": {
- "debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- }
+ "agent-base": "6",
+ "debug": "4"
}
},
"human-signals": {
@@ -2693,10 +2810,16 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
+ "ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true
+ },
"immer": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/immer/-/immer-1.12.1.tgz",
- "integrity": "sha512-3fmKM6ovaqDt0CdC9daXpNi5x/YCYS3i4cwLdTVkhJdk5jrDXoPs7lCm3IqM3yhfSnz4tjjxbRG2CziQ7m8ztg=="
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.5.tgz",
+ "integrity": "sha512-2WuIehr2y4lmYz9gaQzetPR2ECniCifk4ORaQbU3g5EalLt+0IVTosEPJ5BoYl/75ky2mivzdRzV8wWgQGOSYQ=="
},
"import-local": {
"version": "3.0.2",
@@ -2744,12 +2867,6 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
- "ip-regex": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
- "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
- "dev": true
- },
"is-accessor-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
@@ -2858,9 +2975,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.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
"dev": true,
"optional": true
},
@@ -2919,6 +3036,12 @@
"isobject": "^3.0.1"
}
},
+ "is-potential-custom-element-name": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+ "dev": true
+ },
"is-reference": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
@@ -3066,48 +3189,47 @@
}
},
"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.6.3",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz",
+ "integrity": "sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==",
"dev": true,
"requires": {
- "@jest/core": "^25.5.4",
+ "@jest/core": "^26.6.3",
"import-local": "^3.0.2",
- "jest-cli": "^25.5.4"
+ "jest-cli": "^26.6.3"
},
"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==",
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz",
+ "integrity": "sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==",
"dev": true,
"requires": {
- "@jest/core": "^25.5.4",
- "@jest/test-result": "^25.5.0",
- "@jest/types": "^25.5.0",
- "chalk": "^3.0.0",
+ "@jest/core": "^26.6.3",
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "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.6.3",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
"prompts": "^2.0.1",
- "realpath-native": "^2.0.0",
- "yargs": "^15.3.1"
+ "yargs": "^15.4.1"
}
}
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz",
+ "integrity": "sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==",
"dev": true,
"requires": {
- "@jest/types": "^25.5.0",
- "execa": "^3.2.0",
+ "@jest/types": "^26.6.2",
+ "execa": "^4.0.0",
"throat": "^5.0.0"
},
"dependencies": {
@@ -3123,9 +3245,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.1.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
+ "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
"dev": true,
"requires": {
"cross-spawn": "^7.0.0",
@@ -3135,7 +3257,6 @@
"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"
}
@@ -3164,12 +3285,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,195 +3305,208 @@
"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.6.3",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz",
+ "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==",
"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.6.3",
+ "@jest/types": "^26.6.2",
+ "babel-jest": "^26.6.3",
+ "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.6.2",
+ "jest-environment-node": "^26.6.2",
+ "jest-get-type": "^26.3.0",
+ "jest-jasmine2": "^26.6.3",
+ "jest-regex-util": "^26.0.0",
+ "jest-resolve": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
"micromatch": "^4.0.2",
- "pretty-format": "^25.5.0",
- "realpath-native": "^2.0.0"
+ "pretty-format": "^26.6.2"
}
},
"jest-diff": {
- "version": "25.5.0",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.5.0.tgz",
- "integrity": "sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==",
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz",
+ "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==",
"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.6.2",
+ "jest-get-type": "^26.3.0",
+ "pretty-format": "^26.6.2"
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz",
+ "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==",
"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.6.2",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^26.3.0",
+ "jest-util": "^26.6.2",
+ "pretty-format": "^26.6.2"
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz",
+ "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==",
"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.6.2",
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "jest-mock": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jsdom": "^16.4.0"
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz",
+ "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==",
"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.6.2",
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "jest-mock": "^26.6.2",
+ "jest-util": "^26.6.2"
}
},
"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.3.0",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz",
+ "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==",
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz",
+ "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==",
"dev": true,
"requires": {
- "@jest/types": "^25.5.0",
+ "@jest/types": "^26.6.2",
"@types/graceful-fs": "^4.1.2",
+ "@types/node": "*",
"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-regex-util": "^26.0.0",
+ "jest-serializer": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-worker": "^26.6.2",
"micromatch": "^4.0.2",
"sane": "^4.0.3",
- "walker": "^1.0.7",
- "which": "^2.0.2"
+ "walker": "^1.0.7"
}
},
"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.6.3",
+ "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz",
+ "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==",
"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.6.2",
+ "@jest/source-map": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
"co": "^4.6.0",
- "expect": "^25.5.0",
+ "expect": "^26.6.2",
"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.6.2",
+ "jest-matcher-utils": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-runtime": "^26.6.3",
+ "jest-snapshot": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "pretty-format": "^26.6.2",
"throat": "^5.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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz",
+ "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==",
"dev": true,
"requires": {
- "jest-get-type": "^25.2.6",
- "pretty-format": "^25.5.0"
+ "jest-get-type": "^26.3.0",
+ "pretty-format": "^26.6.2"
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz",
+ "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==",
"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.6.2",
+ "jest-get-type": "^26.3.0",
+ "pretty-format": "^26.6.2"
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz",
+ "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
- "@jest/types": "^25.5.0",
- "@types/stack-utils": "^1.0.1",
- "chalk": "^3.0.0",
+ "@jest/types": "^26.6.2",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
"graceful-fs": "^4.2.4",
"micromatch": "^4.0.2",
+ "pretty-format": "^26.6.2",
"slash": "^3.0.0",
- "stack-utils": "^1.0.1"
+ "stack-utils": "^2.0.2"
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz",
+ "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==",
"dev": true,
"requires": {
- "@jest/types": "^25.5.0"
+ "@jest/types": "^26.6.2",
+ "@types/node": "*"
}
},
"jest-pnp-resolver": {
@@ -3388,179 +3516,219 @@
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz",
+ "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==",
"dev": true,
"requires": {
- "@jest/types": "^25.5.0",
- "browser-resolve": "^1.11.3",
- "chalk": "^3.0.0",
+ "@jest/types": "^26.6.2",
+ "chalk": "^4.0.0",
"graceful-fs": "^4.2.4",
- "jest-pnp-resolver": "^1.2.1",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^26.6.2",
"read-pkg-up": "^7.0.1",
- "realpath-native": "^2.0.0",
- "resolve": "^1.17.0",
+ "resolve": "^1.18.1",
"slash": "^3.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.6.3",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz",
+ "integrity": "sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==",
"dev": true,
"requires": {
- "@jest/types": "^25.5.0",
- "jest-regex-util": "^25.2.6",
- "jest-snapshot": "^25.5.1"
+ "@jest/types": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-snapshot": "^26.6.2"
}
},
"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.6.3",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz",
+ "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==",
"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.6.2",
+ "@jest/environment": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.7.1",
"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.6.3",
+ "jest-docblock": "^26.0.0",
+ "jest-haste-map": "^26.6.2",
+ "jest-leak-detector": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-resolve": "^26.6.2",
+ "jest-runtime": "^26.6.3",
+ "jest-util": "^26.6.2",
+ "jest-worker": "^26.6.2",
"source-map-support": "^0.5.6",
"throat": "^5.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.6.3",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz",
+ "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==",
"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.6.2",
+ "@jest/environment": "^26.6.2",
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/globals": "^26.6.2",
+ "@jest/source-map": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
"@types/yargs": "^15.0.0",
- "chalk": "^3.0.0",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^0.6.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.6.3",
+ "jest-haste-map": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-mock": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-resolve": "^26.6.2",
+ "jest-snapshot": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
"slash": "^3.0.0",
"strip-bom": "^4.0.0",
- "yargs": "^15.3.1"
+ "yargs": "^15.4.1"
}
},
"jest-serializer": {
- "version": "25.5.0",
- "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.5.0.tgz",
- "integrity": "sha512-LxD8fY1lByomEPflwur9o4e2a5twSQ7TaVNLlFUuToIdoJuBt8tzHfCsZ42Ok6LkKXWzFWf3AGmheuLAA7LcCA==",
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz",
+ "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==",
"dev": true,
"requires": {
+ "@types/node": "*",
"graceful-fs": "^4.2.4"
}
},
"jest-snapshot": {
- "version": "25.5.1",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.5.1.tgz",
- "integrity": "sha512-C02JE1TUe64p2v1auUJ2ze5vcuv32tkv9PyhEb318e8XOKF7MOyXdJ7kdjbvrp3ChPLU2usI7Rjxs97Dj5P0uQ==",
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz",
+ "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==",
"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.6.2",
+ "@types/babel__traverse": "^7.0.4",
+ "@types/prettier": "^2.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^26.6.2",
"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",
- "make-dir": "^3.0.0",
+ "jest-diff": "^26.6.2",
+ "jest-get-type": "^26.3.0",
+ "jest-haste-map": "^26.6.2",
+ "jest-matcher-utils": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-resolve": "^26.6.2",
"natural-compare": "^1.4.0",
- "pretty-format": "^25.5.0",
- "semver": "^6.3.0"
+ "pretty-format": "^26.6.2",
+ "semver": "^7.3.2"
+ },
+ "dependencies": {
+ "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==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz",
+ "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==",
"dev": true,
"requires": {
- "@jest/types": "^25.5.0",
- "chalk": "^3.0.0",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
"graceful-fs": "^4.2.4",
"is-ci": "^2.0.0",
- "make-dir": "^3.0.0"
+ "micromatch": "^4.0.2"
}
},
"jest-validate": {
- "version": "25.5.0",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-25.5.0.tgz",
- "integrity": "sha512-okUFKqhZIpo3jDdtUXUZ2LxGUZJIlfdYBvZb1aczzxrlyMlqdnnws9MOxezoLGhSaFc2XYaHNReNQfj5zPIWyQ==",
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz",
+ "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==",
"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.6.2",
+ "camelcase": "^6.0.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^26.3.0",
"leven": "^3.1.0",
- "pretty-format": "^25.5.0"
+ "pretty-format": "^26.6.2"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz",
+ "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==",
+ "dev": true
+ }
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz",
+ "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==",
"dev": true,
"requires": {
- "@jest/test-result": "^25.5.0",
- "@jest/types": "^25.5.0",
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
"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.6.2",
+ "string-length": "^4.0.1"
}
},
"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.6.2",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
+ "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
"dev": true,
"requires": {
+ "@types/node": "*",
"merge-stream": "^2.0.0",
"supports-color": "^7.0.0"
}
@@ -3594,37 +3762,51 @@
"dev": true
},
"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.6.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.6.0.tgz",
+ "integrity": "sha512-Ty1vmF4NHJkolaEmdjtxTfSfkdb8Ywarwf63f+F8/mDD1uLSSWDxDuMiZxiPhwunLrn9LOSVItWj4bLYsLN3Dg==",
"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.5",
+ "acorn": "^8.2.4",
+ "acorn-globals": "^6.0.0",
+ "cssom": "^0.4.4",
+ "cssstyle": "^2.3.0",
+ "data-urls": "^2.0.0",
+ "decimal.js": "^10.2.1",
+ "domexception": "^2.0.1",
+ "escodegen": "^2.0.0",
+ "form-data": "^3.0.0",
+ "html-encoding-sniffer": "^2.0.1",
+ "http-proxy-agent": "^4.0.1",
+ "https-proxy-agent": "^5.0.0",
+ "is-potential-custom-element-name": "^1.0.1",
"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",
- "tough-cookie": "^3.0.1",
- "w3c-hr-time": "^1.0.1",
- "w3c-xmlserializer": "^1.1.2",
- "webidl-conversions": "^4.0.2",
+ "parse5": "6.0.1",
+ "saxes": "^5.0.1",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^4.0.0",
+ "w3c-hr-time": "^1.0.2",
+ "w3c-xmlserializer": "^2.0.0",
+ "webidl-conversions": "^6.1.0",
"whatwg-encoding": "^1.0.5",
"whatwg-mimetype": "^2.3.0",
- "whatwg-url": "^7.0.0",
- "ws": "^7.0.0",
+ "whatwg-url": "^8.5.0",
+ "ws": "^7.4.5",
"xml-name-validator": "^3.0.0"
+ },
+ "dependencies": {
+ "form-data": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+ "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ }
}
},
"jsesc": {
@@ -3760,27 +3942,6 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"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=",
- "dev": true
- },
- "lodash.sortby": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
- "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",
@@ -3824,12 +3985,6 @@
"semver": "^6.0.0"
}
},
- "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",
@@ -3927,13 +4082,21 @@
"dev": true
},
"micromatch": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
- "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+ "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
"dev": true,
"requires": {
"braces": "^3.0.1",
- "picomatch": "^2.0.5"
+ "picomatch": "^2.2.3"
+ },
+ "dependencies": {
+ "picomatch": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+ "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
+ "dev": true
+ }
}
},
"micromodal": {
@@ -3941,12 +4104,6 @@
"resolved": "https://registry.npmjs.org/micromodal/-/micromodal-0.4.6.tgz",
"integrity": "sha512-2VDso2a22jWPpqwuWT/4RomVpoU3Bl9qF9D01xzwlNp5UVsImeA0gY4nSpF44vqcQtQOtkiMUV9EZkAJSRxBsg=="
},
- "mime": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz",
- "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==",
- "dev": true
- },
"mime-db": {
"version": "1.45.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
@@ -4061,6 +4218,12 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
+ "node-fetch": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
+ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
+ "dev": true
+ },
"node-gyp": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
@@ -4113,6 +4276,15 @@
"integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
"dev": true
},
+ "node-libpng": {
+ "version": "0.2.18",
+ "resolved": "https://registry.npmjs.org/node-libpng/-/node-libpng-0.2.18.tgz",
+ "integrity": "sha512-nr2j+Qn68ocw/0mfj09Yg8AEEdjrrQYMnFAWi8wLpwe2FMdLr36OFalIEkrJnwpqQxDybfqw7l1GH2wJ98wUIw==",
+ "dev": true,
+ "requires": {
+ "request": "^2.88.2"
+ }
+ },
"node-modules-regexp": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
@@ -4120,31 +4292,72 @@
"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": "8.0.2",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.2.tgz",
+ "integrity": "sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==",
"dev": true,
"optional": true,
"requires": {
"growly": "^1.3.0",
- "is-wsl": "^2.1.1",
- "semver": "^6.3.0",
+ "is-wsl": "^2.2.0",
+ "semver": "^7.3.2",
"shellwords": "^0.1.1",
- "which": "^1.3.1"
+ "uuid": "^8.3.0",
+ "which": "^2.0.2"
},
"dependencies": {
+ "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==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "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": {
"isexe": "^2.0.0"
}
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true,
+ "optional": true
}
}
},
+ "node-releases": {
+ "version": "1.1.72",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz",
+ "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==",
+ "dev": true
+ },
"node-sass": {
"version": "4.14.1",
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz",
@@ -4500,9 +4713,9 @@
}
},
"parse5": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
- "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
+ "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
"dev": true
},
"pascalcase": {
@@ -4530,9 +4743,9 @@
"dev": true
},
"path-parse": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
- "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"path-type": {
@@ -4594,6 +4807,15 @@
"node-modules-regexp": "^1.0.0"
}
},
+ "pixelmatch": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.2.1.tgz",
+ "integrity": "sha512-WjcAdYSnKrrdDdqTcVEY7aB7UhhwjYQKYhHiBXdJef0MOaQeYpUdQ+iVyBLa5YBKS8MPVPPMX7rpOByISLpeEQ==",
+ "dev": true,
+ "requires": {
+ "pngjs": "^4.0.1"
+ }
+ },
"pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
@@ -4603,10 +4825,10 @@
"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==",
+ "pngjs": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-4.0.1.tgz",
+ "integrity": "sha512-rf5+2/ioHeQxR6IxuYNYGFytUyG3lma/WW1nsmjeHlWwtb2aByla6dkVc8pmJ9nplzkTA0q2xx7mMWrOTqT4Gg==",
"dev": true
},
"posix-character-classes": {
@@ -4622,15 +4844,15 @@
"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.6.2",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
+ "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
"dev": true,
"requires": {
- "@jest/types": "^25.5.0",
+ "@jest/types": "^26.6.2",
"ansi-regex": "^5.0.0",
"ansi-styles": "^4.0.0",
- "react-is": "^16.12.0"
+ "react-is": "^17.0.1"
},
"dependencies": {
"ansi-regex": {
@@ -4648,15 +4870,15 @@
"dev": true
},
"progress": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
- "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz",
+ "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==",
"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.4.1",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz",
+ "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==",
"dev": true,
"requires": {
"kleur": "^3.0.3",
@@ -4725,38 +4947,36 @@
"dev": true
},
"puppeteer": {
- "version": "1.20.0",
- "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.20.0.tgz",
- "integrity": "sha512-bt48RDBy2eIwZPrkgbcwHtb51mj2nKvHOPMaSH2IsWiv7lOG9k9zhaRzpDZafrk05ajMc3cu+lSQYYOfH2DkVQ==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-10.0.0.tgz",
+ "integrity": "sha512-AxHvCb9IWmmP3gMW+epxdj92Gglii+6Z4sb+W+zc2hTTu10HF0yg6hGXot5O74uYkVqG3lfDRLfnRpi6WOwi5A==",
"dev": true,
"requires": {
- "debug": "^4.1.0",
- "extract-zip": "^1.6.6",
- "https-proxy-agent": "^2.2.1",
- "mime": "^2.0.3",
- "progress": "^2.0.1",
- "proxy-from-env": "^1.0.0",
- "rimraf": "^2.6.1",
- "ws": "^6.1.0"
+ "debug": "4.3.1",
+ "devtools-protocol": "0.0.883894",
+ "extract-zip": "2.0.1",
+ "https-proxy-agent": "5.0.0",
+ "node-fetch": "2.6.1",
+ "pkg-dir": "4.2.0",
+ "progress": "2.0.1",
+ "proxy-from-env": "1.1.0",
+ "rimraf": "3.0.2",
+ "tar-fs": "2.0.0",
+ "unbzip2-stream": "1.3.3",
+ "ws": "7.4.6"
},
"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"
- }
+ "devtools-protocol": {
+ "version": "0.0.883894",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.883894.tgz",
+ "integrity": "sha512-33idhm54QJzf3Q7QofMgCvIVSd2o9H3kQPWaKT/fhoZh+digc+WSiMhbkeG3iN79WY4Hwr9G05NpbhEVrsOYAg==",
+ "dev": true
},
"ws": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
- "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
- "dev": true,
- "requires": {
- "async-limiter": "~1.0.0"
- }
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
+ "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
+ "dev": true
}
}
},
@@ -4767,9 +4987,9 @@
"dev": true
},
"react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true
},
"read-pkg": {
@@ -4826,12 +5046,6 @@
}
}
},
- "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",
@@ -4859,9 +5073,9 @@
"dev": true
},
"repeat-element": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
- "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz",
+ "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==",
"dev": true
},
"repeat-string": {
@@ -4919,38 +5133,6 @@
}
}
},
- "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==",
- "dev": true,
- "requires": {
- "lodash": "^4.17.19"
- }
- },
- "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==",
- "dev": true,
- "requires": {
- "request-promise-core": "1.1.4",
- "stealthy-require": "^1.1.1",
- "tough-cookie": "^2.3.3"
- },
- "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"
- }
- }
- }
- },
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -5400,12 +5582,12 @@
}
},
"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": {
@@ -5738,9 +5920,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.3",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==",
"dev": true,
"requires": {
"escape-string-regexp": "^2.0.0"
@@ -5784,37 +5966,20 @@
"readable-stream": "^2.0.1"
}
},
- "stealthy-require": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
- "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
- "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.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
"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"
- }
- }
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.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==",
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
+ "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
@@ -5911,9 +6076,9 @@
}
},
"supports-hyperlinks": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz",
- "integrity": "sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz",
+ "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==",
"dev": true,
"requires": {
"has-flag": "^4.0.0",
@@ -5937,6 +6102,44 @@
"inherits": "2"
}
},
+ "tar-fs": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.0.tgz",
+ "integrity": "sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==",
+ "dev": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "mkdirp": "^0.5.1",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.0.0"
+ }
+ },
+ "tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "dev": true,
+ "requires": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
"terminal-link": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
@@ -5964,6 +6167,12 @@
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
"dev": true
},
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
"tmpl": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
@@ -6018,23 +6227,23 @@
}
},
"tough-cookie": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",
- "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
+ "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
"dev": true,
"requires": {
- "ip-regex": "^2.1.0",
- "psl": "^1.1.28",
- "punycode": "^2.1.1"
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.1.2"
}
},
"tr46": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
- "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz",
+ "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==",
"dev": true,
"requires": {
- "punycode": "^2.1.0"
+ "punycode": "^2.1.1"
}
},
"trim-newlines": {
@@ -6052,28 +6261,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": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+ "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==",
"dev": true
},
"tslint": {
@@ -6158,6 +6349,12 @@
"requires": {
"has-flag": "^3.0.0"
}
+ },
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
}
}
},
@@ -6168,6 +6365,14 @@
"dev": true,
"requires": {
"tslib": "^1.8.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ }
}
},
"tunnel-agent": {
@@ -6206,12 +6411,6 @@
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"dev": true
},
- "typedarray": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
- "dev": true
- },
"typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
@@ -6222,11 +6421,21 @@
}
},
"typescript": {
- "version": "3.9.7",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
- "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz",
+ "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==",
"dev": true
},
+ "unbzip2-stream": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz",
+ "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==",
+ "dev": true,
+ "requires": {
+ "buffer": "^5.2.1",
+ "through": "^2.3.8"
+ }
+ },
"union-value": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
@@ -6239,6 +6448,12 @@
"set-value": "^2.0.1"
}
},
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
"unset-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
@@ -6325,9 +6540,9 @@
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"v8-to-istanbul": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz",
- "integrity": "sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ==",
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz",
+ "integrity": "sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==",
"dev": true,
"requires": {
"@types/istanbul-lib-coverage": "^2.0.1",
@@ -6380,13 +6595,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 +6613,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 +6634,20 @@
"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.5.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.5.0.tgz",
+ "integrity": "sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg==",
"dev": true,
"requires": {
- "lodash.sortby": "^4.7.0",
- "tr46": "^1.0.1",
- "webidl-conversions": "^4.0.2"
+ "lodash": "^4.7.0",
+ "tr46": "^2.0.2",
+ "webidl-conversions": "^6.1.0"
}
},
"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"
@@ -6538,9 +6751,9 @@
}
},
"ws": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz",
- "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==",
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
+ "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
"dev": true
},
"xml-name-validator": {
diff --git a/ui/package.json b/ui/package.json
index 4a2cadf..0f14f33 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -20,7 +20,7 @@
"devtools-protocol": "0.0.847576",
"events": "^3.1.0",
"hsluv": "^0.1.0",
- "immer": "^1.12.1",
+ "immer": "^9.0.2",
"micromodal": "^0.4.6",
"mithril": "^2.0.4",
"noice-json-rpc": "^1.2.0",
@@ -32,23 +32,25 @@
"devDependencies": {
"@rollup/plugin-commonjs": "^14.0.0",
"@rollup/plugin-node-resolve": "^8.4.0",
- "@types/jest": "^22.2.3",
- "@types/puppeteer": "^1.20.6",
+ "@types/jest": "^26.0.23",
+ "@types/pixelmatch": "^5.2.3",
+ "@types/puppeteer": "^5.4.3",
"dingusjs": "^0.0.3",
- "jest": "^25.5.4",
+ "jest": "^26.6.3",
+ "node-libpng": "^0.2.18",
"node-sass": "^4.14.1",
"node-watch": "^0.7.1",
- "puppeteer": "^1.20.0",
+ "pixelmatch": "^5.2.1",
+ "puppeteer": "^10.0.0",
"rollup": "^2.38.5",
"rollup-plugin-re": "^1.0.7",
"rollup-plugin-sourcemaps": "^0.6.3",
- "ts-jest": "^25.5.1",
- "tslib": "^1.13.0",
+ "tslib": "^2.2.0",
"tslint": "^5.20.1",
- "typescript": "^3.9.3"
+ "typescript": "^4.2.4"
},
"scripts": {
"build": "node build.js",
- "test": "node build.js --run-tests"
+ "test": "node build.js --run-unittests"
}
}
diff --git a/ui/release/OWNERS b/ui/release/OWNERS
index fe8fd04..30f2fb4 100644
--- a/ui/release/OWNERS
+++ b/ui/release/OWNERS
@@ -1,6 +1,8 @@
set noparent
eseckler@google.com
hjd@google.com
+lalitm@google.com
+octaviant@google.com
oysteine@google.com
nyquist@google.com
primiano@google.com
diff --git a/ui/release/channels.json b/ui/release/channels.json
index 04e189d..0ba34d0 100644
--- a/ui/release/channels.json
+++ b/ui/release/channels.json
@@ -2,11 +2,11 @@
"channels": [
{
"name": "stable",
- "rev": "6dd6756ffbdff4f845c4db28e1fd5aed9ba77b56"
+ "rev": "d996f9e27fef14001401a4ae3c82dc24e71517ee"
},
{
"name": "canary",
- "rev": "3e21f613f20779c04b0bcc937f2605b9b05556ad"
+ "rev": "bbb025d604073a713c6c345828aca916b5fa119c"
},
{
"name": "autopush",
@@ -14,3 +14,4 @@
}
]
}
+
diff --git a/ui/run-tests b/ui/run-all-tests
similarity index 77%
copy from ui/run-tests
copy to ui/run-all-tests
index d06f7d2..7974fa1 100755
--- a/ui/run-tests
+++ b/ui/run-all-tests
@@ -15,4 +15,6 @@
UI_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-$UI_DIR/node $UI_DIR/build.js --run-tests "$@"
+$UI_DIR/node $UI_DIR/build.js "$@" # Build just once.
+$UI_DIR/node $UI_DIR/build.js --no-build --run-unittests "$@"
+$UI_DIR/node $UI_DIR/build.js --no-build --run-integrationtests "$@"
diff --git a/ui/run-tests b/ui/run-integrationtests
similarity index 91%
copy from ui/run-tests
copy to ui/run-integrationtests
index d06f7d2..abcbf4a 100755
--- a/ui/run-tests
+++ b/ui/run-integrationtests
@@ -15,4 +15,4 @@
UI_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-$UI_DIR/node $UI_DIR/build.js --run-tests "$@"
+$UI_DIR/node $UI_DIR/build.js --run-integrationtests "$@"
diff --git a/ui/run-tests b/ui/run-unittests
similarity index 92%
rename from ui/run-tests
rename to ui/run-unittests
index d06f7d2..7ebdf42 100755
--- a/ui/run-tests
+++ b/ui/run-unittests
@@ -15,4 +15,4 @@
UI_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-$UI_DIR/node $UI_DIR/build.js --run-tests "$@"
+$UI_DIR/node $UI_DIR/build.js --run-unittests "$@"
diff --git a/ui/src/assets/common.scss b/ui/src/assets/common.scss
index 0324899..e03adcf 100644
--- a/ui/src/assets/common.scss
+++ b/ui/src/assets/common.scss
@@ -91,6 +91,13 @@
overscroll-behavior: none;
}
+// This is to minimize Mac vs Linux Chrome Headless rendering differences
+// when running UI intergrationtests via puppeteer.
+body.testing {
+ -webkit-font-smoothing: antialiased !important;
+ font-kerning: none !important;
+}
+
h1,
h2,
h3 {
@@ -177,36 +184,6 @@
overflow: hidden;
}
-.video-panel {
- position: relative;
- background-color: #262f3c;
-}
-
-.video-panel-setting {
- position: sticky;
- word-wrap: break-word;
- font-weight: 400;
- font-size: 15px;
- font-family: 'Raleway', sans-serif;
- line-height: 1.5;
- padding: 10px 10px 0px 10px;
- width: 320px;
- color: #fff
-}
-
-.video-panel-message {
- position: sticky;
- word-wrap: break-word;
- font-weight: 400;
- font-size: 12px;
- font-family: 'Raleway', sans-serif;
- line-height: 1.5;
- padding: 10px 10px 10px 10px;
- width: 320px;
- border-bottom: 1px solid #404854;
- color: #b4b7ba;
-}
-
.alerts {
* {
user-select: text;
@@ -230,15 +207,34 @@
.query-table-container {
width: 100%;
- overflow-x: auto;
}
.query-table {
width: 100%;
- border-collapse: collapse;
font-size: 14px;
border: 0;
+ &.pivot-table{
+ thead, i {
+ cursor: pointer;
+ td.drop-location {
+ background-color: hsla(210, 38%, 95%, 1);
+ }
+ .total-aggregation {
+ white-space: pre;
+ font-weight: 600;
+ font-size: 12px
+ }
+ }
+ td {
+ height: 25px;
+ }
+ .disabled {
+ cursor: default;
+ }
+ }
thead td {
+ position: sticky;
+ top: 0;
background-color: hsl(214, 22%, 90%);
color: #262f3c;
text-align: center;
@@ -318,6 +314,14 @@
background-color: #ebeef9;
}
+ .chip {
+ background-color: #bed6ff;
+ border-radius: 3px;
+ font-size: smaller;
+ padding: 0 0.1rem;
+ margin-left: 1ch;
+ }
+
h1 {
grid-area: title;
color: hsl(213, 22%, 30%);
@@ -642,3 +646,114 @@
.disallow-selection {
user-select: none;
}
+
+.pivot-table-editor-container {
+ font: inherit;
+ width: 670px;
+ height: 420px;
+ h2 {
+ font-weight: bold;
+ text-align: left;
+ }
+ label {
+ cursor: pointer;
+ }
+ select {
+ font-weight: 100;
+ margin: 3px;
+ color: #333;
+ font-size: 15px;
+ align-items: center;
+ cursor: pointer;
+ }
+ span:nth-of-type(2) {
+ margin-left: 1rem;
+ }
+ section.table-group {
+ display: table-row;
+ table {
+ margin: 15px;
+ td {
+ width: 300px;
+ font-size: 17px;
+ cursor: pointer;
+ &.drop-location {
+ background-color: hsla(0, 0%, 85%, 1);
+ }
+ }
+ th {
+ text-align: center;
+ width: 300px;
+ border-bottom: 1px solid rgba(60, 76, 92, 0.4);
+ }
+ &:first-child {
+ float: left;
+ }
+ &:last-child {
+ float: right;
+ }
+ }
+ }
+ .scroll {
+ height: 150px;
+ overflow: auto;
+ }
+ section.button-group {
+ text-align: center;
+ button {
+ background-color: #262f3c;
+ color: #fff;
+ border-radius: 10px;
+ padding: 2px 5px;
+ font-weight: bold;
+ font-size: 13px;
+ min-width: 7em;
+ margin-right: 1rem;
+ }
+ }
+ section {
+ margin: 1rem;
+ }
+}
+
+.pivot-table-tab {
+ button {
+ background: #262f3c;
+ color: white;
+ border-radius: 10px;
+ font-size: 12px;
+ height: 20px;
+ line-height: 18px;
+ min-width: 7em;
+ margin: 0.2rem;
+ &:disabled {
+ opacity: 0.75;
+ cursor: default;
+ }
+ }
+ span {
+ user-select: text;
+ flex-grow: 1;
+ }
+}
+
+.pivot-table-spinner {
+ display: inline-block;
+ vertical-align: middle;
+ box-sizing: border-box;
+ width: 18px;
+ height: 18px;
+ margin-left: 10px;
+ border-radius: 50%;
+ border: 2px solid #408ee0;
+ border-color: #408ee0 transparent #408ee0 transparent;
+ animation: spinner 1.25s linear infinite;
+ @keyframes spinner {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+ }
+}
+
+.allow-white-space {
+ white-space: pre
+}
diff --git a/ui/src/assets/details.scss b/ui/src/assets/details.scss
index f5196f0..1545e4d 100644
--- a/ui/src/assets/details.scss
+++ b/ui/src/assets/details.scss
@@ -171,7 +171,7 @@
width: 50%;
}
}
- &.heap-profile {
+ &.flamegraph-profile {
display: flex;
justify-content: space-between;
align-content: center;
diff --git a/ui/src/assets/flags_page.scss b/ui/src/assets/flags_page.scss
new file mode 100644
index 0000000..3a1d897
--- /dev/null
+++ b/ui/src/assets/flags_page.scss
@@ -0,0 +1,74 @@
+// 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.
+
+.flags-page {
+ overflow-y: scroll;
+ user-select: text;
+}
+
+.flags-content {
+ max-width: 90ch;
+ width: 60%;
+ margin: 0 auto;
+ padding: 3rem;
+ display: grid;
+ grid-row-gap: 1rem;
+
+ h1 {
+ font-size: larger;
+ }
+
+ button {
+ background: none;
+ border: 1px solid rgb(218, 220, 224);
+ border-radius: 3px;
+ color: rgb(25, 103, 210);
+ font-size: .8125rem;
+ padding: 8px 12px;
+ cursor: pointer;
+ font-weight: 500;
+ }
+}
+
+.flag-widget {
+ display: grid;
+ grid-template:
+ "title control" auto
+ "description control" auto / 1fr auto;
+
+ row-gap: 0.5rem;
+ align-content: center;
+
+ select {
+ grid-area: control;
+ background: white;
+ border: 1px solid rgb(25, 103, 210);
+ color: rgb(25, 103, 210);
+ font-size: .8125rem;
+ height: 1.625rem;
+ letter-spacing: .01em;
+ max-width: 150px;
+ text-align-last: center;
+ width: 100%;
+ }
+
+ label {
+ font-weight: bold;
+ }
+
+ .description {
+ font-size: smaller;
+ }
+}
+
diff --git a/ui/src/assets/perfetto.scss b/ui/src/assets/perfetto.scss
index d3cc23a..24ae99a 100644
--- a/ui/src/assets/perfetto.scss
+++ b/ui/src/assets/perfetto.scss
@@ -23,3 +23,4 @@
@import 'modal';
@import 'details';
@import 'trace_info_page';
+@import 'flags_page';
diff --git a/ui/src/assets/record.scss b/ui/src/assets/record.scss
index 6b0a762..f732e25 100644
--- a/ui/src/assets/record.scss
+++ b/ui/src/assets/record.scss
@@ -201,7 +201,6 @@
li {
@include transition();
- display: block;
height: 55px;
padding: 0 1em;
font-size: 15px;
@@ -612,7 +611,6 @@
}
&.selected {
- background-color: hsl(207, 90%, 74%);
background-color: hsl(88, 50%, 67%);
box-shadow: 0 0 4px 0px #999;
}
@@ -697,7 +695,6 @@
&::-webkit-slider-runnable-track {
margin: 10px;
- border-radius: 1px;
width: 100%;
height: 10px;
background-color : #ddd;
@@ -785,23 +782,22 @@
}
}
+ .chrome-categories {
+ margin: var(--record-section-padding) 0;
+
+ display: flex;
+ flex-direction: row;
+
+ .categories-list {
+ width: 50%;
+ }
+ }
+
.dropdown {
border: 1px solid #eee;
outline: none;
-webkit-appearance: none;
- &:not(.multicolumn) {
- overflow: hidden;
- height: 25px;
- padding: 0 5px;
- &:focus, &:hover {
- height: 30vh;
- position: absolute;
- overflow: auto;
- box-shadow: 0 0 15px 0 #eee;
- }
- }
-
option, optgroup {
@include transition();
min-height: 25px;
@@ -823,6 +819,23 @@
}
}
+ &.singlecolumn {
+ margin: var(--record-section-padding) 0;
+ padding: 0;
+ max-width: 100%;
+ width: 100%;
+ overflow-y: auto;
+ height: 400px;
+ optgroup {
+ display: grid;
+ padding: 0;
+ grid-template-columns: 1fr;
+ }
+ option {
+ margin: 0;
+ }
+ }
+
&.multicolumn {
padding: 0;
max-width: 100%;
diff --git a/ui/src/assets/sidebar.scss b/ui/src/assets/sidebar.scss
index 8bded2f..7bd6dc9 100644
--- a/ui/src/assets/sidebar.scss
+++ b/ui/src/assets/sidebar.scss
@@ -280,6 +280,12 @@
}
}
+// Hide the footer when running integration tests, as the version code and the
+// tiny text with pending queries can fail the screenshot diff test.
+body.testing .sidebar-footer {
+ visibility: hidden;
+}
+
.keycap {
background-color: #fafbfc;
border: 1px solid #d1d5da;
diff --git a/ui/src/assets/typefaces.scss b/ui/src/assets/typefaces.scss
index 5e4ba16..46ad9b4 100644
--- a/ui/src/assets/typefaces.scss
+++ b/ui/src/assets/typefaces.scss
@@ -11,7 +11,7 @@
font-family: 'Raleway';
font-style: normal;
font-weight: 100;
- src: local('Raleway Thin'), local('Raleway-Thin'), url(assets/Raleway-Thin.woff2) format('woff2');
+ src: url(assets/Raleway-Thin.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@@ -20,7 +20,7 @@
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
- src: local('Raleway'), local('Raleway-Regular'), url(assets/Raleway-Regular.woff2) format('woff2');
+ src: url(assets/Raleway-Regular.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@@ -29,7 +29,7 @@
font-family: 'Roboto Condensed';
font-style: normal;
font-weight: 300;
- src: local('Roboto Condensed Light'), local('RobotoCondensed-Light'), url(assets/RobotoCondensed-Light.woff2) format('woff2');
+ src: url(assets/RobotoCondensed-Light.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@@ -38,7 +38,7 @@
font-family: 'Roboto Condensed';
font-style: normal;
font-weight: 400;
- src: local('Roboto Condensed'), local('RobotoCondensed-Regular'), url(assets/RobotoCondensed-Regular.woff2) format('woff2');
+ src: url(assets/RobotoCondensed-Regular.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@@ -47,7 +47,7 @@
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 400;
- src: local('Roboto Mono'), local('RobotoMono-Regular'), url(assets/RobotoMono-Regular.woff2) format('woff2');
+ src: url(assets/RobotoMono-Regular.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
diff --git a/ui/src/base/remote.ts b/ui/src/base/remote.ts
deleted file mode 100644
index 578bd19..0000000
--- a/ui/src/base/remote.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {defer, Deferred} from './deferred';
-
-interface RemoteResponse {
- id: number;
- result: {};
-}
-
-/**
- * A proxy for an object that lives on another thread.
- */
-export class Remote {
- private nextRequestId: number;
- private port: MessagePort;
- // tslint:disable-next-line no-any
- private deferredRequests: Map<number, Deferred<any>>;
-
- constructor(port: MessagePort) {
- this.nextRequestId = 0;
- this.deferredRequests = new Map();
- this.port = port;
- this.port.onmessage = (event: MessageEvent) => {
- this.receive(event.data);
- };
- }
-
- /**
- * Invoke method with name |method| with |args| on the remote object.
- * Optionally set |transferList| to transfer those objects.
- */
- // tslint:disable-next-line no-any
- send<T extends any>(
- method: string,
- args: Array<{}>, transferList?: Transferable[]): Promise<T> {
- const d = defer<T>();
- this.deferredRequests.set(this.nextRequestId, d);
- const message = {
- responseId: this.nextRequestId,
- method,
- args,
- };
- if (transferList === undefined) {
- this.port.postMessage(message);
- } else {
- this.port.postMessage(message, transferList);
- }
- this.nextRequestId += 1;
- return d;
- }
-
- private receive(response: RemoteResponse): void {
- const d = this.deferredRequests.get(response.id);
- if (!d) throw new Error(`No deferred response with ID ${response.id}`);
- this.deferredRequests.delete(response.id);
- d.resolve(response.result);
- }
-}
-
-/**
- * Given a MessagePort |port| where the other end is owned by a Remote
- * (see above) turn each incoming MessageEvent into a call on |handler|
- * and post the result back to the calling thread.
- */
-export function forwardRemoteCalls(
- port: MessagePort,
- // tslint:disable-next-line no-any
- handler: {[key: string]: any}) {
- port.onmessage = (msg: MessageEvent) => {
- const method = msg.data.method;
- const id = msg.data.responseId;
- const args = msg.data.args || [];
- if (method === undefined || id === undefined) {
- throw new Error(`Invalid call method: ${method} id: ${id}`);
- }
-
- if (!(handler[method] instanceof Function)) {
- throw new Error(`Method not known: ${method}(${args})`);
- }
-
- const result = handler[method].apply(handler, args);
- const transferList = [];
-
- if (result !== undefined && result.port instanceof MessagePort) {
- transferList.push(result.port);
- }
-
- port.postMessage(
- {
- id,
- result,
- },
- transferList);
- };
-}
diff --git a/ui/src/base/string_utils.ts b/ui/src/base/string_utils.ts
index bf44d97..019de9e 100644
--- a/ui/src/base/string_utils.ts
+++ b/ui/src/base/string_utils.ts
@@ -27,11 +27,11 @@
// 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;};
+let Utf8Decoder: {decode: (buf: Uint8Array) => string;};
+let Utf8Encoder: {encode: (str: string) => Uint8Array;};
try {
- UTF8Decoder = new TextDecoder('utf-8');
- UTF8Encoder = new TextEncoder();
+ Utf8Decoder = new TextDecoder('utf-8');
+ Utf8Encoder = new TextEncoder();
} catch (_) {
if (typeof process === 'undefined') {
// Silence the warning when we know we are running under NodeJS.
@@ -39,8 +39,8 @@
'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 = {
+ 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);
@@ -62,13 +62,13 @@
}
export function utf8Encode(str: string): Uint8Array {
- return UTF8Encoder.encode(str);
+ 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);
+ return Utf8Decoder.decode(buffer);
}
// The binaryEncode/Decode functions below allow to encode an arbitrary binary
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index cd25c9e..9a14db8 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -16,11 +16,6 @@
import {assertExists, assertTrue} from '../base/logging';
import {randomColor} from '../common/colorizer';
-import {
- ConvertTrace,
- ConvertTraceAndDownload,
- 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';
@@ -30,18 +25,27 @@
} from '../tracks/expected_frames/common';
import {HEAP_PROFILE_TRACK_KIND} from '../tracks/heap_profile/common';
import {
+ PERF_SAMPLES_PROFILE_TRACK_KIND
+} from '../tracks/perf_samples_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 {DEFAULT_VIEWING_OPTION, PERF_SAMPLES_KEY} from './flamegraph_util';
+import {
+ AggregationAttrs,
+ PivotAttrs,
+ SubQueryAttrs,
+ TableAttrs
+} from './pivot_table_common';
import {
AdbRecordingTarget,
Area,
CallsiteInfo,
createEmptyState,
EngineMode,
- HeapProfileFlamegraphViewingOption,
+ FlamegraphStateViewingOption,
LogsPagination,
NewEngineMode,
OmniboxState,
@@ -50,7 +54,6 @@
SCROLLING_TRACK_GROUP,
State,
Status,
- TraceSource,
TraceTime,
TrackKindPriority,
TrackState,
@@ -66,8 +69,12 @@
ACTUAL_FRAMES_SLICE_TRACK_KIND
];
-const lowPriorityTrackOrder =
- [HEAP_PROFILE_TRACK_KIND, COUNTER_TRACK_KIND, ASYNC_SLICE_TRACK_KIND];
+const lowPriorityTrackOrder = [
+ PERF_SAMPLES_PROFILE_TRACK_KIND,
+ HEAP_PROFILE_TRACK_KIND,
+ COUNTER_TRACK_KIND,
+ ASYNC_SLICE_TRACK_KIND
+];
export interface AddTrackArgs {
id?: string;
@@ -80,16 +87,17 @@
}
export interface PostedTrace {
+ buffer: ArrayBuffer;
title: string;
fileName?: string;
url?: string;
- buffer: ArrayBuffer;
+ uuid?: string;
+ localOnly?: boolean;
}
function clearTraceState(state: StateDraft) {
const nextId = state.nextId;
const recordConfig = state.recordConfig;
- const route = state.route;
const recordingTarget = state.recordingTarget;
const updateChromeCategories = state.updateChromeCategories;
const extensionInstalled = state.extensionInstalled;
@@ -100,7 +108,6 @@
Object.assign(state, createEmptyState());
state.nextId = nextId;
state.recordConfig = recordConfig;
- state.route = route;
state.recordingTarget = recordingTarget;
state.updateChromeCategories = updateChromeCategories;
state.extensionInstalled = extensionInstalled;
@@ -125,10 +132,6 @@
export const StateActions = {
- navigate(state: StateDraft, args: {route: string}): void {
- state.route = args.route;
- },
-
openTraceFromFile(state: StateDraft, args: {file: File}): void {
clearTraceState(state);
const id = `${state.nextId++}`;
@@ -137,7 +140,6 @@
ready: false,
source: {type: 'FILE', file: args.file},
};
- state.route = `/viewer`;
},
openTraceFromBuffer(state: StateDraft, args: PostedTrace): void {
@@ -148,7 +150,6 @@
ready: false,
source: {type: 'ARRAY_BUFFER', ...args},
};
- state.route = `/viewer`;
},
openTraceFromUrl(state: StateDraft, args: {url: string}): void {
@@ -159,7 +160,6 @@
ready: false,
source: {type: 'URL', url: args.url},
};
- state.route = `/viewer`;
},
openTraceFromHttpRpc(state: StateDraft, _args: {}): void {
@@ -170,32 +170,10 @@
ready: false,
source: {type: 'HTTP_RPC'},
};
- state.route = `/viewer`;
},
- openVideoFromFile(state: StateDraft, args: {file: File}): void {
- state.video = URL.createObjectURL(args.file);
- state.videoEnabled = true;
- },
-
- // TODO(b/141359485): Actions should only modify state.
- convertTraceToJson(
- _: StateDraft, args: {file: Blob, truncate?: 'start'|'end'}): void {
- ConvertTrace(args.file, 'json', args.truncate);
- },
-
- convertTraceToSystraceAndDownload(_: StateDraft, args: {file: Blob}): void {
- ConvertTraceAndDownload(args.file, 'systrace');
- },
-
- convertTraceToJsonAndDownload(_: StateDraft, args: {file: Blob}): void {
- ConvertTraceAndDownload(args.file, 'json');
- },
-
- convertTraceToPprof(
- _: StateDraft,
- args: {pid: number, src: TraceSource, ts1: number, ts2?: number}): void {
- ConvertTraceToPprof(args.pid, args.src, args.ts1, args.ts2);
+ setTraceUuid(state: StateDraft, args: {traceUuid: string}) {
+ state.traceUuid = args.traceUuid;
},
addTracks(state: StateDraft, args: {tracks: AddTrackArgs[]}) {
@@ -406,6 +384,8 @@
}
},
+ // TODO(hjd): engine.ready should be a published thing. If it's part
+ // of the state it interacts badly with permalinks.
setEngineReady(
state: StateDraft,
args: {engineId: string; ready: boolean, mode: EngineMode}): void {
@@ -470,6 +450,12 @@
// tslint:disable-next-line no-any
(state as any)[key] = (args.newState as any)[key];
}
+
+ // If we're loading from a permalink then none of the engines can
+ // possibly be ready:
+ for (const engine of Object.values(state.engines)) {
+ engine.ready = false;
+ }
},
setRecordConfig(state: StateDraft, args: {config: RecordConfig;}): void {
@@ -485,9 +471,7 @@
}
},
- addNote(
- state: StateDraft,
- args: {timestamp: number, color: string, isMovie: boolean}): void {
+ addNote(state: StateDraft, args: {timestamp: number, color: string}): void {
const id = `${state.nextNoteId++}`;
state.notes[id] = {
noteType: 'DEFAULT',
@@ -496,9 +480,6 @@
color: args.color,
text: '',
};
- if (args.isMovie) {
- state.videoNoteIds.push(id);
- }
this.selectNote(state, {id});
},
@@ -552,34 +533,6 @@
};
},
- toggleVideo(state: StateDraft, _: {}): void {
- state.videoEnabled = !state.videoEnabled;
- if (!state.videoEnabled) {
- state.video = null;
- state.flagPauseEnabled = false;
- state.scrubbingEnabled = false;
- state.videoNoteIds.forEach(id => {
- this.removeNote(state, {id});
- });
- }
- },
-
- toggleFlagPause(state: StateDraft, _: {}): void {
- if (state.video != null) {
- state.flagPauseEnabled = !state.flagPauseEnabled;
- }
- },
-
- toggleScrubbing(state: StateDraft, _: {}): void {
- if (state.video != null) {
- state.scrubbingEnabled = !state.scrubbingEnabled;
- }
- },
-
- setVideoOffset(state: StateDraft, args: {offset: number}): void {
- state.videoOffset = args.offset;
- },
-
changeNoteColor(state: StateDraft, args: {id: string, newColor: string}):
void {
const note = state.notes[args.id];
@@ -595,11 +548,6 @@
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.
@@ -645,14 +593,38 @@
ts: args.ts,
type: args.type,
};
- state.currentHeapProfileFlamegraph = {
- kind: 'HEAP_PROFILE_FLAMEGRAPH',
+ this.openFlamegraph(
+ state, {...args, viewingOption: DEFAULT_VIEWING_OPTION});
+ },
+
+ selectPerfSamples(
+ state: StateDraft,
+ args: {id: number, upid: number, ts: number, type: string}): void {
+ state.currentSelection = {
+ kind: 'PERF_SAMPLES',
id: args.id,
upid: args.upid,
ts: args.ts,
type: args.type,
- viewingOption: DEFAULT_VIEWING_OPTION,
- focusRegex: '',
+ };
+ this.openFlamegraph(state, {...args, viewingOption: PERF_SAMPLES_KEY});
+ },
+
+ openFlamegraph(state: StateDraft, args: {
+ id: number,
+ upid: number,
+ ts: number,
+ type: string,
+ viewingOption: FlamegraphStateViewingOption
+ }): void {
+ state.currentFlamegraphState = {
+ kind: 'FLAMEGRAPH_STATE',
+ id: args.id,
+ upid: args.upid,
+ ts: args.ts,
+ type: args.type,
+ viewingOption: args.viewingOption,
+ focusRegex: ''
};
},
@@ -666,24 +638,24 @@
};
},
- expandHeapProfileFlamegraph(
+ expandFlamegraphState(
state: StateDraft, args: {expandedCallsite?: CallsiteInfo}): void {
- if (state.currentHeapProfileFlamegraph === null) return;
- state.currentHeapProfileFlamegraph.expandedCallsite = args.expandedCallsite;
+ if (state.currentFlamegraphState === null) return;
+ state.currentFlamegraphState.expandedCallsite = args.expandedCallsite;
},
- changeViewHeapProfileFlamegraph(
- state: StateDraft,
- args: {viewingOption: HeapProfileFlamegraphViewingOption}): void {
- if (state.currentHeapProfileFlamegraph === null) return;
- state.currentHeapProfileFlamegraph.viewingOption = args.viewingOption;
- },
+ changeViewFlamegraphState(
+ state: StateDraft, args: {viewingOption: FlamegraphStateViewingOption}):
+ void {
+ if (state.currentFlamegraphState === null) return;
+ state.currentFlamegraphState.viewingOption = args.viewingOption;
+ },
- changeFocusHeapProfileFlamegraph(
- state: StateDraft, args: {focusRegex: string}): void {
- if (state.currentHeapProfileFlamegraph === null) return;
- state.currentHeapProfileFlamegraph.focusRegex = args.focusRegex;
- },
+ changeFocusFlamegraphState(state: StateDraft, args: {focusRegex: string}):
+ void {
+ if (state.currentFlamegraphState === null) return;
+ state.currentFlamegraphState.focusRegex = args.focusRegex;
+ },
selectChromeSlice(
state: StateDraft, args: {id: number, trackId: string, table: string}):
@@ -813,7 +785,7 @@
},
setVisibleTraceTime(state: StateDraft, args: VisibleState): void {
- state.frontendLocalState.visibleState = args;
+ state.frontendLocalState.visibleState = {...args};
},
setChromeCategories(state: StateDraft, args: {categories: string[]}): void {
@@ -860,6 +832,121 @@
}
state.metrics.selectedIndex = args.index;
},
+
+ togglePerfDebug(state: StateDraft, _: {}): void {
+ state.perfDebug = !state.perfDebug;
+ },
+
+ toggleSidebar(state: StateDraft, _: {}): void {
+ state.sidebarVisible = !state.sidebarVisible;
+ },
+
+ setHoveredUtidAndPid(state: StateDraft, args: {utid: number, pid: number}) {
+ state.hoveredPid = args.pid;
+ state.hoveredUtid = args.utid;
+ },
+
+ setHighlightedSliceId(state: StateDraft, args: {sliceId: number}) {
+ state.highlightedSliceId = args.sliceId;
+ },
+
+ setHighlightedFlowLeftId(state: StateDraft, args: {flowId: number}) {
+ state.focusedFlowIdLeft = args.flowId;
+ },
+
+ setHighlightedFlowRightId(state: StateDraft, args: {flowId: number}) {
+ state.focusedFlowIdRight = args.flowId;
+ },
+
+ setSearchIndex(state: StateDraft, args: {index: number}) {
+ state.searchIndex = args.index;
+ },
+
+ setHoveredLogsTimestamp(state: StateDraft, args: {ts: number}) {
+ state.hoveredLogsTimestamp = args.ts;
+ },
+
+ setHoveredNoteTimestamp(state: StateDraft, args: {ts: number}) {
+ state.hoveredNoteTimestamp = args.ts;
+ },
+
+ setCurrentTab(state: StateDraft, args: {tab: string|undefined}) {
+ state.currentTab = args.tab;
+ },
+
+ addNewPivotTable(state: StateDraft, args: {
+ name: string,
+ pivotTableId: string,
+ selectedPivots: PivotAttrs[],
+ selectedAggregations: AggregationAttrs[],
+ traceTime?: TraceTime,
+ selectedTrackIds?: number[]
+ }): void {
+ state.pivotTable[args.pivotTableId] = {
+ id: args.pivotTableId,
+ name: args.name,
+ selectedPivots: args.selectedPivots,
+ selectedAggregations: args.selectedAggregations,
+ isLoadingQuery: false,
+ traceTime: args.traceTime,
+ selectedTrackIds: args.selectedTrackIds
+ };
+ },
+
+ deletePivotTable(state: StateDraft, args: {pivotTableId: string}): void {
+ delete state.pivotTable[args.pivotTableId];
+ },
+
+ resetPivotTableRequest(state: StateDraft, args: {pivotTableId: string}):
+ void {
+ state.pivotTable[args.pivotTableId].requestedAction = undefined;
+ },
+
+ setPivotTableRequest(
+ state: StateDraft,
+ args: {pivotTableId: string, action: string, attrs?: SubQueryAttrs}):
+ void {
+ state.pivotTable[args.pivotTableId].requestedAction = {
+ action: args.action,
+ attrs: args.attrs
+ };
+ },
+
+ setAvailablePivotTableColumns(
+ state: StateDraft,
+ args: {availableColumns: TableAttrs[], availableAggregations: string[]}):
+ void {
+ state.pivotTableConfig.availableColumns = args.availableColumns;
+ state.pivotTableConfig.availableAggregations =
+ args.availableAggregations;
+ },
+
+ toggleQueryLoading(state: StateDraft, args: {pivotTableId: string}): void {
+ state.pivotTable[args.pivotTableId].isLoadingQuery =
+ !state.pivotTable[args.pivotTableId].isLoadingQuery;
+ },
+
+ setSelectedPivotsAndAggregations(state: StateDraft, args: {
+ pivotTableId: string,
+ selectedPivots: PivotAttrs[],
+ selectedAggregations: AggregationAttrs[]
+ }) {
+ state.pivotTable[args.pivotTableId].selectedPivots =
+ args.selectedPivots.map(pivot => Object.assign({}, pivot));
+ state.pivotTable[args.pivotTableId].selectedAggregations =
+ args.selectedAggregations.map(
+ aggregation => Object.assign({}, aggregation));
+ },
+
+ setPivotTableRange(state: StateDraft, args: {
+ pivotTableId: string,
+ traceTime?: TraceTime,
+ selectedTrackIds?: number[]
+ }) {
+ const pivotTable = state.pivotTable[args.pivotTableId];
+ pivotTable.traceTime = args.traceTime;
+ pivotTable.selectedTrackIds = args.selectedTrackIds;
+ }
};
// 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..85eaba8 100644
--- a/ui/src/common/actions_unittest.ts
+++ b/ui/src/common/actions_unittest.ts
@@ -14,6 +14,7 @@
import {produce} from 'immer';
+import {assertExists} from '../base/logging';
import {SLICE_TRACK_KIND} from '../tracks/chrome_slices/common';
import {HEAP_PROFILE_TRACK_KIND} from '../tracks/heap_profile/common';
import {
@@ -81,13 +82,6 @@
return state;
}
-test('navigate', () => {
- const after = produce(createEmptyState(), draft => {
- StateActions.navigate(draft, {route: '/foo'});
- });
- expect(after.route).toBe('/foo');
-});
-
test('add scrolling tracks', () => {
const once = produce(createEmptyState(), draft => {
StateActions.addTrack(draft, {
@@ -278,7 +272,6 @@
expect(engineKeys.length).toBe(1);
expect((after.engines[engineKeys[0]].source as TraceUrlSource).url)
.toBe('https://example.com/bar');
- expect(after.route).toBe('/viewer');
expect(after.recordConfig).toBe(recordConfig);
});
@@ -311,7 +304,6 @@
.toBe('https://example.com/foo');
expect(thrice.pinnedTracks.length).toBe(0);
expect(thrice.scrollingTracks.length).toBe(0);
- expect(thrice.route).toBe('/viewer');
});
test('setEngineReady with missing engine is ignored', () => {
@@ -426,3 +418,29 @@
expect(after.trackGroups['g'].tracks).toEqual(['a', 'a', 'c', 'b']);
});
+
+test('perf samples open flamegraph', () => {
+ const state = createEmptyState();
+ const perfType = 'perf';
+
+ const afterSelectingPerf = produce(state, draft => {
+ StateActions.selectPerfSamples(
+ draft, {id: 0, upid: 0, ts: 0, type: perfType});
+ });
+
+ expect(assertExists(afterSelectingPerf.currentFlamegraphState).type)
+ .toBe(perfType);
+});
+
+test('heap profile opens flamegraph', () => {
+ const state = createEmptyState();
+ const heapType = 'graph';
+
+ const afterSelectingPerf = produce(state, draft => {
+ StateActions.selectHeapProfile(
+ draft, {id: 0, upid: 0, ts: 0, type: heapType});
+ });
+
+ expect(assertExists(afterSelectingPerf.currentFlamegraphState).type)
+ .toBe(heapType);
+});
diff --git a/ui/src/common/cache_manager.ts b/ui/src/common/cache_manager.ts
new file mode 100644
index 0000000..d946253
--- /dev/null
+++ b/ui/src/common/cache_manager.ts
@@ -0,0 +1,119 @@
+// 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 file deals with caching traces in the browser's Cache storage. The
+ * traces are cached so that the UI can gracefully reload a trace when the tab
+ * containing it is discarded by Chrome(e.g. because the tab was not used for a
+ * long time) or when the user accidentally hits reload.
+ */
+import {assertExists} from '../base/logging';
+import {TraceArrayBufferSource, TraceSource} from './state';
+
+const TRACE_CACHE_NAME = 'cached_traces';
+const TRACE_CACHE_SIZE = 10;
+
+export async function cacheTrace(
+ traceSource: TraceSource, traceUuid: string): Promise<boolean> {
+ let trace, title = '', fileName = '', url = '', contentLength = 0,
+ localOnly = false;
+ switch (traceSource.type) {
+ case 'ARRAY_BUFFER':
+ trace = traceSource.buffer;
+ title = traceSource.title;
+ fileName = traceSource.fileName || '';
+ url = traceSource.url || '';
+ contentLength = traceSource.buffer.byteLength;
+ localOnly = traceSource.localOnly || false;
+ break;
+ case 'FILE':
+ trace = await traceSource.file.arrayBuffer();
+ title = traceSource.file.name;
+ contentLength = traceSource.file.size;
+ break;
+ default:
+ return false;
+ }
+ assertExists(trace);
+
+ const headers = new Headers([
+ ['x-trace-title', title],
+ ['x-trace-url', url],
+ ['x-trace-filename', fileName],
+ ['x-trace-local-only', `${localOnly}`],
+ ['content-type', 'application/octet-stream'],
+ ['content-length', `${contentLength}`],
+ [
+ 'expires',
+ // Expires in a week from now (now = upload time)
+ (new Date((new Date()).getTime() + (1000 * 60 * 60 * 24 * 7)))
+ .toUTCString()
+ ]
+ ]);
+ const traceCache = await caches.open(TRACE_CACHE_NAME);
+ await deleteStaleEntries(traceCache);
+ await traceCache.put(
+ `/_${TRACE_CACHE_NAME}/${traceUuid}`, new Response(trace, {headers}));
+ return true;
+}
+
+export async function tryGetTrace(traceUuid: string):
+ Promise<TraceArrayBufferSource|undefined> {
+ await deleteStaleEntries(await caches.open(TRACE_CACHE_NAME));
+ const response = await caches.match(
+ `/_${TRACE_CACHE_NAME}/${traceUuid}`, {cacheName: TRACE_CACHE_NAME});
+
+ if (!response) return undefined;
+ return {
+ type: 'ARRAY_BUFFER',
+ buffer: await response.arrayBuffer(),
+ title: response.headers.get('x-trace-title') || '',
+ fileName: response.headers.get('x-trace-filename') || undefined,
+ url: response.headers.get('x-trace-url') || undefined,
+ uuid: traceUuid,
+ localOnly: response.headers.get('x-trace-local-only') === 'true'
+ };
+}
+
+async function deleteStaleEntries(traceCache: Cache) {
+ /*
+ * Loop through stored caches and invalidate all but the most recent 10.
+ */
+ const keys = await traceCache.keys();
+ const storedTraces: Array<{key: Request, date: Date}> = [];
+ for (const key of keys) {
+ const existingTrace = assertExists(await traceCache.match(key));
+ const expiryDate =
+ new Date(assertExists(existingTrace.headers.get('expires')));
+ if (expiryDate < new Date()) {
+ await traceCache.delete(key);
+ } else {
+ storedTraces.push({key, date: expiryDate});
+ }
+ }
+
+ if (storedTraces.length <= TRACE_CACHE_SIZE) return;
+
+ /*
+ * Sort the traces descending by time, such that most recent ones are placed
+ * at the beginning. Then, take traces from TRACE_CACHE_SIZE onwards and
+ * delete them from cache.
+ */
+ const oldTraces =
+ storedTraces.sort((a, b) => b.date.getTime() - a.date.getTime())
+ .slice(TRACE_CACHE_SIZE);
+ for (const oldTrace of oldTraces) {
+ await traceCache.delete(oldTrace.key);
+ }
+}
diff --git a/ui/src/common/canvas_utils.ts b/ui/src/common/canvas_utils.ts
index 96c0fc9..0835bad 100644
--- a/ui/src/common/canvas_utils.ts
+++ b/ui/src/common/canvas_utils.ts
@@ -71,22 +71,22 @@
ctx: CanvasRenderingContext2D,
x: number,
y: number,
- length: number,
width: number,
+ height: number,
color: string) {
ctx.beginPath();
ctx.fillStyle = color;
- const triangleSize = width / 4;
+ const triangleSize = height / 4;
ctx.moveTo(x, y);
- ctx.lineTo(x + length, y);
- ctx.lineTo(x + length - 3, y + triangleSize * 0.5);
- ctx.lineTo(x + length, y + triangleSize);
- ctx.lineTo(x + length - 3, y + (triangleSize * 1.5));
- ctx.lineTo(x + length, y + 2 * triangleSize);
- ctx.lineTo(x + length - 3, y + (triangleSize * 2.5));
- ctx.lineTo(x + length, y + 3 * triangleSize);
- ctx.lineTo(x + length - 3, y + (triangleSize * 3.5));
- ctx.lineTo(x + length, y + 4 * triangleSize);
- ctx.lineTo(x, y + width);
+ ctx.lineTo(x + width, y);
+ ctx.lineTo(x + width - 3, y + triangleSize * 0.5);
+ ctx.lineTo(x + width, y + triangleSize);
+ ctx.lineTo(x + width - 3, y + (triangleSize * 1.5));
+ ctx.lineTo(x + width, y + 2 * triangleSize);
+ ctx.lineTo(x + width - 3, y + (triangleSize * 2.5));
+ ctx.lineTo(x + width, y + 3 * triangleSize);
+ ctx.lineTo(x + width - 3, y + (triangleSize * 3.5));
+ ctx.lineTo(x + width, y + 4 * triangleSize);
+ ctx.lineTo(x, y + height);
ctx.fill();
}
\ No newline at end of file
diff --git a/ui/src/common/channels.ts b/ui/src/common/channels.ts
new file mode 100644
index 0000000..ad0837c
--- /dev/null
+++ b/ui/src/common/channels.ts
@@ -0,0 +1,49 @@
+// 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 {globals} from '../frontend/globals';
+
+const DEFAULT_CHANNEL = 'stable';
+const CHANNEL_KEY = 'perfettoUiChannel';
+
+let currentChannel: string|undefined = undefined;
+let nextChannel: string|undefined = undefined;
+
+// This is the channel the UI is currently running. It doesn't change once the
+// UI has been loaded.
+export function getCurrentChannel(): string {
+ if (currentChannel === undefined) {
+ currentChannel = localStorage.getItem(CHANNEL_KEY) || DEFAULT_CHANNEL;
+ }
+ return currentChannel;
+}
+
+// This is the channel that will be applied on reload.
+export function getNextChannel(): string {
+ if (nextChannel !== undefined) {
+ return nextChannel;
+ }
+ return getCurrentChannel();
+}
+
+export function channelChanged(): boolean {
+ return getCurrentChannel() !== getNextChannel();
+}
+
+export function setChannel(channel: string): void {
+ getCurrentChannel(); // Cache the current channel before mangling next one.
+ nextChannel = channel;
+ localStorage.setItem(CHANNEL_KEY, channel);
+ globals.rafScheduler.scheduleFullRedraw();
+}
diff --git a/ui/src/common/colorizer.ts b/ui/src/common/colorizer.ts
index 9adde38..5ff5e78 100644
--- a/ui/src/common/colorizer.ts
+++ b/ui/src/common/colorizer.ts
@@ -159,3 +159,16 @@
const lightness = isSelected ? 30 : hash(sliceName + 'x', 40) + 40;
return [hue, saturation, lightness];
}
+
+// Lightens the color for thread slices to represent wall time.
+export function hslForThreadIdleSlice(
+ hue: number,
+ saturation: number,
+ lightness: number,
+ isSelected: boolean|null): [number, number, number] {
+ // Increase lightness by 80% when selected and 40% otherwise,
+ // without exceeding 88.
+ let newLightness = isSelected ? lightness * 1.8 : lightness * 1.4;
+ newLightness = Math.min(newLightness, 88);
+ return [hue, saturation, newLightness];
+}
diff --git a/ui/src/common/engine.ts b/ui/src/common/engine.ts
index 6d77b0f..065df54 100644
--- a/ui/src/common/engine.ts
+++ b/ui/src/common/engine.ts
@@ -21,14 +21,13 @@
ComputeMetricArgs,
ComputeMetricResult,
QueryArgs,
- RawQueryArgs,
- RawQueryResult
} from './protos';
-import {NUM, NUM_NULL, slowlyCountRows, STR} from './query_iterator';
+import {NUM, NUM_NULL, STR} from './query_result';
import {
createQueryResult,
+ QueryError,
QueryResult,
- WritableQueryResult
+ WritableQueryResult,
} from './query_result';
import {TimeSpan} from './time';
@@ -46,7 +45,6 @@
endLoading(): void {}
}
-export class QueryError extends Error {}
// This is used to skip the decoding of queryResult from protobufjs and deal
// with it ourselves. See the comment below around `QueryResult.decode = ...`.
@@ -78,7 +76,6 @@
private pendingParses = new Array<Deferred<void>>();
private pendingEOFs = new Array<Deferred<void>>();
private pendingQueries = new Array<WritableQueryResult>();
- private pendingRawQueries = new Array<Deferred<RawQueryResult>>();
private pendingRestoreTables = new Array<Deferred<void>>();
private pendingComputeMetrics = new Array<Deferred<ComputeMetricResult>>();
@@ -148,7 +145,6 @@
};
const rpc = TraceProcessorRpc.decode(rpcMsgEncoded);
- this.loadingTracker.endLoading();
if (rpc.fatalError !== undefined && rpc.fatalError.length > 0) {
throw new Error(`${rpc.fatalError}`);
@@ -164,6 +160,8 @@
this.rxSeqId = rpc.seq;
+ let isFinalResponse = true;
+
switch (rpc.response) {
case TPM.TPM_APPEND_TRACE_DATA:
const appendResult = assertExists(rpc.appendResult);
@@ -186,12 +184,10 @@
pendingQuery.appendResultBatch(qRes.rawQueryResult);
if (pendingQuery.isComplete()) {
this.pendingQueries.shift();
+ } else {
+ isFinalResponse = false;
}
break;
- case TPM.TPM_QUERY_RAW_DEPRECATED:
- const queryRes = assertExists(rpc.rawQueryResult) as RawQueryResult;
- assertExists(this.pendingRawQueries.shift()).resolve(queryRes);
- break;
case TPM.TPM_COMPUTE_METRIC:
const metricRes = assertExists(rpc.metricResult) as ComputeMetricResult;
if (metricRes.error && metricRes.error.length > 0) {
@@ -204,6 +200,10 @@
'Unexpected TraceProcessor response received: ', rpc.response);
break;
} // switch(rpc.response);
+
+ if (isFinalResponse) {
+ this.loadingTracker.endLoading();
+ }
}
/**
@@ -268,53 +268,6 @@
return asyncRes;
}
- /**
- * Runs a SQL query and throws if the query failed.
- * Queries performed by the controller logic should use this.
- */
- 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;
- }
-
- /**
- * Runs a SQL query. Does not throw if the query fails.
- * The caller must handle this failure. This is so this function can be safely
- * used for user-typed SQL.
- */
- uncheckedQuery(sqlQuery: string): Promise<RawQueryResult> {
- const asyncRes = defer<RawQueryResult>();
- this.pendingRawQueries.push(asyncRes);
- const rpc = TraceProcessorRpc.create();
- rpc.request = TPM.TPM_QUERY_RAW_DEPRECATED;
- rpc.rawQueryArgs = new RawQueryArgs();
- rpc.rawQueryArgs.sqlQuery = sqlQuery;
- rpc.rawQueryArgs.timeQueuedNs = Math.floor(performance.now() * 1e6);
- this.rpcSendRequest(rpc);
- return asyncRes;
- }
-
- async queryOneRow(query: string): Promise<number[]> {
- const result = await this.query(query);
- const res: number[] = [];
- if (slowlyCountRows(result) === 0) return res;
- for (const col of result.columns) {
- if (col.longValues!.length === 0) {
- console.error(
- `queryOneRow should only be used for queries that return long values
- : ${query}`);
- throw new Error(
- `queryOneRow should only be used for queries that return long values
- : ${query}`);
- }
- res.push(+col.longValues![0]);
- }
- return res;
- }
-
/*
* Issues a streaming query and retrieve results in batches.
* The returned QueryResult object will be populated over time with batches
@@ -324,7 +277,7 @@
* the rows incrementally.
*
* Example usage:
- * const res = engine.queryV2('SELECT foo, bar FROM table');
+ * const res = engine.query('SELECT foo, bar FROM table');
* console.log(res.numRows()); // Will print 0 because we didn't await.
* await(res.waitAllRows());
* console.log(res.numRows()); // Will print the total number of rows.
@@ -332,10 +285,8 @@
* for (const it = res.iter({foo: NUM, bar:STR}); it.valid(); it.next()) {
* console.log(it.foo, it.bar);
* }
- * TODO(primiano): in next CLs move everything on queryV2, then rename it to
- * just query(), and delete the old (columnar, non-streaming) query() method.
*/
- queryV2(sqlQuery: string): Promise<QueryResult>&QueryResult {
+ query(sqlQuery: string): Promise<QueryResult>&QueryResult {
const rpc = TraceProcessorRpc.create();
rpc.request = TPM.TPM_QUERY_STREAMING;
rpc.queryArgs = new QueryArgs();
@@ -366,7 +317,7 @@
async getCpus(): Promise<number[]> {
if (!this._cpus) {
const cpus = [];
- const queryRes = await this.queryV2(
+ const queryRes = await this.query(
'select distinct(cpu) as cpu from sched order by cpu;');
for (const it = queryRes.iter({cpu: NUM}); it.valid(); it.next()) {
cpus.push(it.cpu);
@@ -383,7 +334,7 @@
from gpu_counter_track
where name = 'gpufreq';
`);
- this._numGpus = +result.columns[0].longValues![0];
+ this._numGpus = result.firstRow({gpuCount: NUM}).gpuCount;
}
return this._numGpus;
}
@@ -391,26 +342,33 @@
// TODO: This should live in code that's more specific to chrome, instead of
// in engine.
async getNumberOfProcesses(): Promise<number> {
- const result = await this.queryV2('select count(*) as cnt from process;');
+ const result = await this.query('select count(*) as cnt from process;');
return result.firstRow({cnt: NUM}).cnt;
}
async getTraceTimeBounds(): Promise<TimeSpan> {
- const query = `select start_ts, end_ts from trace_bounds`;
- const res = (await this.queryOneRow(query));
- return new TimeSpan(res[0] / 1e9, res[1] / 1e9);
+ const result = await this.query(
+ `select start_ts as startTs, end_ts as endTs from trace_bounds`);
+ const bounds = result.firstRow({
+ startTs: NUM,
+ endTs: NUM,
+ });
+ return new TimeSpan(bounds.startTs / 1e9, bounds.endTs / 1e9);
}
async getTracingMetadataTimeBounds(): Promise<TimeSpan> {
- const queryRes = await this.queryV2(`select name, int_value from metadata
+ const queryRes = await this.query(`select
+ name,
+ int_value as intValue
+ 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 = queryRes.iter({'name': STR, 'int_value': NUM_NULL});
+ const it = queryRes.iter({'name': STR, 'intValue': NUM_NULL});
for (; it.valid(); it.next()) {
const columnName = it.name;
- const timestamp = it.int_value;
+ const timestamp = it.intValue;
if (timestamp === null) continue;
if (columnName === 'tracing_disabled_ns') {
endBound = Math.min(endBound, timestamp / 1e9);
diff --git a/ui/src/common/feature_flags.ts b/ui/src/common/feature_flags.ts
new file mode 100644
index 0000000..b0cc39f
--- /dev/null
+++ b/ui/src/common/feature_flags.ts
@@ -0,0 +1,230 @@
+// 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 file should not import anything else. Since the flags will be used from
+// ~everywhere and the are "statically" initialized (i.e. files construct Flags
+// at import time) if this file starts importing anything we will quickly run
+// into issues with initialization order which will be a pain.
+
+interface FlagSettings {
+ id: string;
+ defaultValue: boolean;
+ description: string;
+ name?: string;
+}
+
+export enum OverrideState {
+ DEFAULT = 'DEFAULT',
+ TRUE = 'OVERRIDE_TRUE',
+ FALSE = 'OVERRIDE_FALSE',
+}
+
+export interface FlagStore {
+ load(): object;
+ save(o: object): void;
+}
+
+// Stored state for a number of flags.
+interface FlagOverrides {
+ [id: string]: OverrideState;
+}
+
+// Check if the given object is a valid FlagOverrides.
+// This is necessary since someone could modify the persisted flags
+// behind our backs.
+function isFlagOverrides(o: object): o is FlagOverrides {
+ const states =
+ [OverrideState.TRUE.toString(), OverrideState.FALSE.toString()];
+ for (const v of Object.values(o)) {
+ if (typeof v !== 'string' || !states.includes(v)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+class Flags {
+ private store: FlagStore;
+ private flags: Map<string, FlagImpl>;
+ private overrides: FlagOverrides;
+
+ constructor(store: FlagStore) {
+ this.store = store;
+ this.flags = new Map();
+ this.overrides = {};
+ this.load();
+ }
+
+ register(settings: FlagSettings): Flag {
+ const id = settings.id;
+ if (this.flags.has(id)) {
+ throw new Error(`Flag with id "${id}" is already registered.`);
+ }
+
+ const saved = this.overrides[id];
+ const state = saved === undefined ? OverrideState.DEFAULT : saved;
+ const flag = new FlagImpl(this, state, settings);
+ this.flags.set(id, flag);
+ return flag;
+ }
+
+ allFlags(): Flag[] {
+ return [...this.flags.values()];
+ }
+
+ resetAll() {
+ for (const flag of this.flags.values()) {
+ flag.state = OverrideState.DEFAULT;
+ }
+ this.save();
+ }
+
+ load(): void {
+ const o = this.store.load();
+ if (isFlagOverrides(o)) {
+ this.overrides = o;
+ }
+ }
+
+ save(): void {
+ for (const flag of this.flags.values()) {
+ if (flag.isOverridden()) {
+ this.overrides[flag.id] = flag.state;
+ } else {
+ delete this.overrides[flag.id];
+ }
+ }
+
+ this.store.save(this.overrides);
+ }
+}
+
+export interface Flag {
+ // A unique identifier for this flag ("magicSorting")
+ readonly id: string;
+
+ // The name of the flag the user sees ("New track sorting algorithm")
+ readonly name: string;
+
+ // A longer description which is displayed to the user.
+ // "Sort tracks using an embedded tfLite model based on your expression
+ // while waiting for the trace to load."
+ readonly description: string;
+
+ // Whether the flag defaults to true or false.
+ // If !flag.isOverridden() then flag.get() === flag.defaultValue
+ readonly defaultValue: boolean;
+
+ // Get the current value of the flag.
+ get(): boolean;
+
+ // Override the flag and persist the new value.
+ set(value: boolean): void;
+
+ // If the flag has been overridden.
+ // Note: A flag can be overridden to its default value.
+ isOverridden(): boolean;
+
+ // Reset the flag to its default setting.
+ reset(): void;
+
+ // Get the current state of the flag.
+ overriddenState(): OverrideState;
+}
+
+class FlagImpl implements Flag {
+ registry: Flags;
+ state: OverrideState;
+
+ readonly id: string;
+ readonly name: string;
+ readonly description: string;
+ readonly defaultValue: boolean;
+
+ constructor(registry: Flags, state: OverrideState, settings: FlagSettings) {
+ this.registry = registry;
+ this.id = settings.id;
+ this.state = state;
+ this.description = settings.description;
+ this.defaultValue = settings.defaultValue;
+ this.name = settings.name || settings.id;
+ }
+
+ get(): boolean {
+ switch (this.state) {
+ case OverrideState.TRUE:
+ return true;
+ case OverrideState.FALSE:
+ return false;
+ case OverrideState.DEFAULT:
+ default:
+ return this.defaultValue;
+ }
+ }
+
+ set(value: boolean): void {
+ const next = value ? OverrideState.TRUE : OverrideState.FALSE;
+ if (this.state === next) {
+ return;
+ }
+ this.state = next;
+ this.registry.save();
+ }
+
+ overriddenState(): OverrideState {
+ return this.state;
+ }
+
+ reset() {
+ this.state = OverrideState.DEFAULT;
+ this.registry.save();
+ }
+
+ isOverridden(): boolean {
+ return this.state !== OverrideState.DEFAULT;
+ }
+}
+
+class LocalStorageStore implements FlagStore {
+ static KEY = 'perfettoFeatureFlags';
+
+ load(): object {
+ const s = localStorage.getItem(LocalStorageStore.KEY);
+ let parsed: object;
+ try {
+ parsed = JSON.parse(s || '{}');
+ } catch (e) {
+ return {};
+ }
+ if (typeof parsed !== 'object' || parsed === null) {
+ return {};
+ }
+ return parsed;
+ }
+
+ save(o: object): void {
+ const s = JSON.stringify(o);
+ localStorage.setItem(LocalStorageStore.KEY, s);
+ }
+}
+
+export const FlagsForTesting = Flags;
+export const featureFlags = new Flags(new LocalStorageStore());
+
+export const PERF_SAMPLE_FLAG = featureFlags.register({
+ id: 'perfSampleFlamegraph',
+ name: 'Perf Sample Flamegraph',
+ description: 'Show flamegraph generated by a perf sample.',
+ defaultValue: false
+});
diff --git a/ui/src/common/feature_flags_unittest.ts b/ui/src/common/feature_flags_unittest.ts
new file mode 100644
index 0000000..d2cb97b
--- /dev/null
+++ b/ui/src/common/feature_flags_unittest.ts
@@ -0,0 +1,118 @@
+// 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 {FlagsForTesting as Flags, FlagStore} from './feature_flags';
+
+class TestFlagStore implements FlagStore {
+ o: object = {};
+
+ load(): object {
+ return this.o;
+ }
+
+ save(o: object): void {
+ this.o = o;
+ }
+}
+
+test('create flag', () => {
+ const flags = new Flags(new TestFlagStore());
+ const myFlag = flags.register({
+ id: 'myFlag',
+ defaultValue: false,
+ description: '',
+ });
+ expect(myFlag.get()).toEqual(false);
+ expect(myFlag.isOverridden()).toEqual(false);
+});
+
+test('registering the same flag twice is an error', () => {
+ const flags = new Flags(new TestFlagStore());
+ flags.register({
+ id: 'foo',
+ defaultValue: false,
+ description: '',
+ });
+ expect(() => flags.register({
+ id: 'foo',
+ defaultValue: false,
+ description: '',
+ })).toThrow('Flag with id "foo" is already registered.');
+});
+
+test('can override', () => {
+ const flags = new Flags(new TestFlagStore());
+ const foo = flags.register({
+ id: 'foo',
+ defaultValue: false,
+ description: '',
+ });
+ foo.set(true);
+ expect(foo.isOverridden()).toEqual(true);
+ expect(foo.get()).toEqual(true);
+});
+
+test('overrides are persisted', () => {
+ const store = new TestFlagStore();
+ const flagsA = new Flags(store);
+ const fooA = flagsA.register({
+ id: 'foo',
+ defaultValue: true,
+ description: 'some description',
+ });
+
+ fooA.set(true);
+
+ const flagsB = new Flags(store);
+ const fooB = flagsB.register({
+ id: 'foo',
+ defaultValue: false,
+ description: 'a new description',
+ });
+
+ expect(fooB.get()).toEqual(true);
+ expect(fooB.isOverridden()).toEqual(true);
+});
+
+test('flags can be reset', () => {
+ const flags = new Flags(new TestFlagStore());
+ const foo = flags.register({
+ id: 'foo',
+ defaultValue: false,
+ description: 'some description',
+ });
+
+ foo.set(false);
+ foo.reset();
+ expect(foo.get()).toEqual(false);
+ expect(foo.isOverridden()).toEqual(false);
+});
+
+test('corrupt store is ignored', () => {
+ class Store {
+ load(): object {
+ return {'foo': 'bad state'};
+ }
+
+ save(_: object): void {}
+ }
+ const flags = new Flags(new Store());
+ const foo = flags.register({
+ id: 'foo',
+ defaultValue: false,
+ description: 'some description',
+ });
+
+ expect(foo.isOverridden()).toEqual(false);
+});
diff --git a/ui/src/common/flamegraph_util.ts b/ui/src/common/flamegraph_util.ts
index 2910952..c8070ff 100644
--- a/ui/src/common/flamegraph_util.ts
+++ b/ui/src/common/flamegraph_util.ts
@@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {CallsiteInfo} from '../common/state';
+import {CallsiteInfo} from './state';
export const SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY = 'SPACE';
export const ALLOC_SPACE_MEMORY_ALLOCATED_KEY = 'ALLOC_SPACE';
export const OBJECTS_ALLOCATED_NOT_FREED_KEY = 'OBJECTS';
export const OBJECTS_ALLOCATED_KEY = 'ALLOC_OBJECTS';
+export const PERF_SAMPLES_KEY = 'PERF_SAMPLES';
export const DEFAULT_VIEWING_OPTION = SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY;
diff --git a/ui/src/common/immer_init.ts b/ui/src/common/immer_init.ts
new file mode 100644
index 0000000..b0ecf01
--- /dev/null
+++ b/ui/src/common/immer_init.ts
@@ -0,0 +1,27 @@
+// 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 {enablePatches, setAutoFreeze} from 'immer';
+
+export function initializeImmerJs() {
+ enablePatches();
+
+ // TODO(primiano): re-enable this, requires fixing some bugs that this bubbles
+ // up. This is a new feature of immer which freezes object after a produce().
+ // Unfortunately we piled up a bunch of bugs where we shallow-copy objects
+ // from the global state (which is frozen) and later try to update the copies.
+ // By doing so, we accidentally the local copy of global state, which is
+ // supposed to be immutable.
+ setAutoFreeze(false);
+}
diff --git a/ui/src/common/pivot_table_common.ts b/ui/src/common/pivot_table_common.ts
new file mode 100644
index 0000000..ac463e5
--- /dev/null
+++ b/ui/src/common/pivot_table_common.ts
@@ -0,0 +1,186 @@
+// 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 {getHiddenPivotAlias} from './pivot_table_query_generator';
+import {Row} from './query_result';
+
+export const AVAILABLE_TABLES = ['slice'];
+export const AVAILABLE_AGGREGATIONS = ['COUNT', 'SUM', 'AVG', 'MIN', 'MAX'];
+export const WHERE_FILTERS = ['slice.dur != -1'];
+export const SLICE_STACK_HELPER_COLUMNS =
+ ['depth', 'stack_id', 'parent_stack_id'];
+export const SLICE_STACK_COLUMN = 'name (stack)';
+export const DEFAULT_PIVOT_TABLE_ID = 'pivot-table';
+export const SLICE_AGGREGATION_PIVOT_TABLE_ID = 'pivot-table-slices';
+
+export interface AggregationAttrs {
+ tableName: string;
+ columnName: string;
+ aggregation: string;
+ order: string;
+}
+
+export interface PivotAttrs {
+ tableName: string;
+ columnName: string;
+ isStackPivot: boolean;
+}
+
+export interface TableAttrs {
+ tableName: string;
+ columns: string[];
+}
+
+export interface ColumnAttrs {
+ name: string;
+ index: number;
+ tableName: string;
+ columnName: string;
+ aggregation?: string;
+ order?: string;
+ isStackColumn: boolean;
+}
+
+export interface RowAttrs {
+ row: Row;
+ expandableColumns: Set<string>; // Columns at which the row can be expanded.
+ expandedRows: Map<string, {
+ isExpanded: boolean,
+ rows: RowAttrs[]
+ }>; // Contains the expanded rows of each expanded expandableColumn.
+ whereFilters: Map<string, string>; // Where filters of each column that
+ // joins the row with its parent.
+ loadingColumn?: string;
+ depth: number;
+}
+
+export interface SubQueryAttrs {
+ rowIndices: number[];
+ columnIdx: number;
+ value: string;
+ expandedRowColumns: string[];
+}
+
+export interface SubQueryAttrs {
+ rowIndices: number[];
+ columnIdx: number;
+ value: string;
+}
+
+export interface PivotTableQueryResponse {
+ columns: ColumnAttrs[];
+ error?: string;
+ durationMs: number;
+ rows: RowAttrs[];
+ totalAggregations?: Row;
+}
+
+// Determine if the column provided is a stack column that can be expanded
+// into descendants.
+export function isStackPivot(tableName: string, columnName: string) {
+ if (tableName === 'slice' && columnName === SLICE_STACK_COLUMN) {
+ return true;
+ }
+ return false;
+}
+
+// Get the helper columns that are needed to expand a stack pivot.
+export function getHiddenStackHelperColumns(pivot: PivotAttrs) {
+ const hiddenColumns: Array<{pivotAttrs: PivotAttrs, columnAlias: string}> =
+ [];
+ if (pivot.tableName === 'slice') {
+ for (const column of SLICE_STACK_HELPER_COLUMNS) {
+ const pivotAttrs = {
+ tableName: pivot.tableName,
+ columnName: column,
+ isStackPivot: false
+ };
+ hiddenColumns.push(
+ {pivotAttrs, columnAlias: getHiddenPivotAlias(pivotAttrs)});
+ }
+ }
+ return hiddenColumns;
+}
+
+// Removing unnecessary columns from table and adding stack column if it exists.
+export function removeHiddenAndAddStackColumns(
+ tableName: string, columns: string[]) {
+ if (tableName === 'slice') {
+ // Removing "cat" and "slice_id" to maintain the original schema of the
+ // slice table that's compatible with descendant_slice_by_stack table.
+ columns = columns.filter(
+ column => ['stack_id', 'parent_stack_id', 'cat', 'slice_id'].includes(
+ column) === false);
+ columns.push(SLICE_STACK_COLUMN);
+ }
+ return columns;
+}
+
+// Get a list of tables that include the descendants that need to be queried.
+export function getDescendantsTables(pivots: PivotAttrs[], stackId: string) {
+ const descendantsTables = [...AVAILABLE_TABLES];
+ let descendantsTable = 'undefined_table';
+ let replaceIdx = -1;
+ if (pivots.length > 0 && pivots[0].tableName === 'slice') {
+ // Replace slice table with descendants table.
+ descendantsTable = `descendant_slice_by_stack(${stackId}) AS slice`;
+ replaceIdx = descendantsTables.indexOf('slice');
+ if (replaceIdx === -1) {
+ throw Error('Slice table not found.');
+ }
+ }
+ if (pivots.length === 0 ||
+ !isStackPivot(pivots[0].tableName, pivots[0].columnName) ||
+ replaceIdx === -1) {
+ throw Error('Invalid Arguments to "getDescendantsTables"');
+ }
+ descendantsTables[replaceIdx] = descendantsTable;
+ return descendantsTables;
+}
+
+// Get the stack id column in the stack pivot table.
+export function getStackColumn(pivot: PivotAttrs) {
+ if (pivot.tableName === 'slice') {
+ return {tableName: 'slice', columnName: 'stack_id', isStackPivot: false};
+ }
+ throw Error('"getStackColumn" called on pivot that is not a stack column.');
+}
+
+// Get the parent stack id column in the stack pivot table.
+export function getParentStackColumn(pivot: PivotAttrs) {
+ if (pivot.tableName === 'slice') {
+ return {
+ tableName: 'slice',
+ columnName: 'parent_stack_id',
+ isStackPivot: false
+ };
+ }
+ throw Error(
+ '"getParentStackColumn" called on pivot that is not a stack column.');
+}
+
+// Get the depth column in the stack pivot table.
+export function getStackDepthColumn(pivot: PivotAttrs) {
+ if (pivot.tableName === 'slice') {
+ return {tableName: 'slice', columnName: 'depth', isStackPivot: false};
+ }
+ throw Error(
+ '"getStackDepthColumn" called on pivot that is not a stack column.');
+}
+
+// Get a where filter that restricts the query by the given stack id.
+export function getParentStackWhereFilter(pivot: PivotAttrs, stackId: string) {
+ const stackColumn = getStackColumn(pivot);
+ return `${stackColumn.tableName}.${stackColumn.columnName} = ${stackId}`;
+}
diff --git a/ui/src/common/pivot_table_query_generator.ts b/ui/src/common/pivot_table_query_generator.ts
new file mode 100644
index 0000000..1e55eb6
--- /dev/null
+++ b/ui/src/common/pivot_table_query_generator.ts
@@ -0,0 +1,321 @@
+// 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 {
+ AggregationAttrs,
+ AVAILABLE_TABLES,
+ getHiddenStackHelperColumns,
+ getParentStackWhereFilter,
+ getStackColumn,
+ getStackDepthColumn,
+ PivotAttrs,
+} from './pivot_table_common';
+
+export function getPivotAlias(pivot: PivotAttrs): string {
+ return `${pivot.tableName} ${pivot.columnName}`;
+}
+
+export function getHiddenPivotAlias(pivot: PivotAttrs) {
+ return getPivotAlias(pivot) + ' (hidden)';
+}
+
+export function getAggregationAlias(aggregation: AggregationAttrs): string {
+ return `${aggregation.tableName} ${aggregation.columnName} (${
+ aggregation.aggregation})`;
+}
+
+export function getSqlPivotAlias(pivot: PivotAttrs): string {
+ return `"${getPivotAlias(pivot)}"`;
+}
+
+export function getSqlHiddenPivotAlias(pivot: PivotAttrs): string {
+ return `"${getHiddenPivotAlias(pivot)}"`;
+}
+
+export function getSqlAggregationAlias(aggregation: AggregationAttrs): string {
+ return `"${getAggregationAlias(aggregation)}"`;
+}
+
+export function getAggregationOverStackAlias(aggregation: AggregationAttrs):
+ string {
+ return `${getAggregationAlias(aggregation)} (stack)`;
+}
+
+export function getSqlAggregationOverStackAlias(aggregation: AggregationAttrs):
+ string {
+ return `"${getAggregationOverStackAlias(aggregation)}"`;
+}
+
+export function getTotalAggregationAlias(aggregation: AggregationAttrs):
+ string {
+ return `${getAggregationAlias(aggregation)} (total)`;
+}
+
+export function getSqlTotalAggregationAlias(aggregation: AggregationAttrs):
+ string {
+ return `"${getTotalAggregationAlias(aggregation)}"`;
+}
+
+// Returns an array of pivot aliases along with any additional pivot aliases.
+export function getSqlAliasedPivotColumns(pivots: PivotAttrs[]): string[] {
+ const pivotCols = [];
+ for (const pivot of pivots) {
+ pivotCols.push(getSqlPivotAlias(pivot));
+ if (pivot.isStackPivot) {
+ pivotCols.push(...getHiddenStackHelperColumns(pivot).map(
+ column => `"${column.columnAlias}"`));
+ }
+ }
+ return pivotCols;
+}
+
+export function getAliasedPivotColumns(pivots: PivotAttrs[]) {
+ const pivotCols: Array<{pivotAttrs: PivotAttrs, columnAlias: string}> = [];
+ for (const pivot of pivots) {
+ pivotCols.push({pivotAttrs: pivot, columnAlias: getPivotAlias(pivot)});
+ if (pivot.isStackPivot) {
+ pivotCols.push(...getHiddenStackHelperColumns(pivot));
+ }
+ }
+ return pivotCols;
+}
+
+// Returns an array of aggregation aliases along with total aggregations if
+// necessary.
+function getSqlAliasedAggregationsColumns(
+ aggregations: AggregationAttrs[],
+ hasPivotsSelected: boolean,
+ isStackQuery: boolean): string[] {
+ const aggCols =
+ aggregations.map(aggregation => getSqlAggregationAlias(aggregation));
+
+ if (hasPivotsSelected) {
+ aggCols.push(...aggregations.map(
+ aggregation => getSqlTotalAggregationAlias(aggregation)));
+ }
+
+ if (isStackQuery) {
+ aggCols.push(...aggregations.map(
+ aggregation => getSqlAggregationOverStackAlias(aggregation)));
+ }
+ return aggCols;
+}
+
+export class PivotTableQueryGenerator {
+ // Generates a query that selects all pivots and aggregations and joins any
+ // tables needed by them together. All pivots are renamed into the format
+ // tableName columnName and all aggregations are renamed into
+ // tableName columnName (aggregation) (see getPivotAlias or
+ // getAggregationAlias).
+ private generateJoinQuery(
+ pivots: PivotAttrs[], aggregations: AggregationAttrs[],
+ whereFilters: string[], joinTables: string[]): string {
+ let joinQuery = 'SELECT\n';
+
+ const pivotCols = [];
+ for (const pivot of pivots) {
+ if (pivot.isStackPivot) {
+ pivotCols.push(
+ `${pivot.tableName}.name AS ` +
+ `${getSqlPivotAlias(pivot)}`);
+
+ pivotCols.push(...getHiddenStackHelperColumns(pivot).map(
+ column => `${column.pivotAttrs.tableName}.${
+ column.pivotAttrs.columnName} AS "${column.columnAlias}"`));
+ } else {
+ pivotCols.push(
+ `${pivot.tableName}.${pivot.columnName} AS ` +
+ `${getSqlPivotAlias(pivot)}`);
+ }
+ }
+
+ const aggCols = [];
+ for (const aggregation of aggregations) {
+ aggCols.push(
+ `${aggregation.tableName}.${aggregation.columnName} AS ` +
+ `${getSqlAggregationAlias(aggregation)}`);
+ }
+
+ joinQuery += pivotCols.concat(aggCols).join(',\n ');
+ joinQuery += '\n';
+ joinQuery += 'FROM\n';
+ joinQuery += joinTables.join(',\n ');
+ joinQuery += '\n';
+ joinQuery += 'WHERE\n';
+ joinQuery += whereFilters.join(' AND\n ');
+ joinQuery += '\n';
+ return joinQuery;
+ }
+
+ // Partitions the aggregations from the subquery generateJoinQuery over
+ // all sets of appended pivots ({pivot1}, {pivot1, pivot2}, etc).
+ private generateAggregationQuery(
+ pivots: PivotAttrs[], aggregations: AggregationAttrs[],
+ whereFilters: string[], joinTables: string[],
+ isStackQuery: boolean): string {
+ // No need for this query if there are no aggregations.
+ if (aggregations.length === 0) {
+ return this.generateJoinQuery(
+ pivots, aggregations, whereFilters, joinTables);
+ }
+
+ let aggQuery = 'SELECT\n';
+ const pivotCols = getSqlAliasedPivotColumns(pivots);
+ let partitionByPivotCols = pivotCols;
+ if (pivots.length > 0 && pivots[0].isStackPivot) {
+ partitionByPivotCols = [];
+ partitionByPivotCols.push(
+ getSqlHiddenPivotAlias(getStackColumn(pivots[0])));
+ partitionByPivotCols.push(...getSqlAliasedPivotColumns(pivots.slice(1)));
+ }
+
+ const aggCols = [];
+ for (const aggregation of aggregations) {
+ const aggColPrefix =
+ `${aggregation.aggregation}(${getSqlAggregationAlias(aggregation)})`;
+
+ if (pivots.length === 0) {
+ // Don't partition over pivots if there are no pivots.
+ aggCols.push(
+ `${aggColPrefix} AS ${getSqlAggregationAlias(aggregation)}`);
+ continue;
+ }
+
+ // Add total aggregations column.
+ aggCols.push(
+ `${aggColPrefix} OVER () AS ` +
+ `${getSqlTotalAggregationAlias(aggregation)}`);
+
+ // Add aggregation over stack column.
+ if (isStackQuery) {
+ aggCols.push(
+ `${aggColPrefix} OVER (PARTITION BY ` +
+ `${partitionByPivotCols[0]}) AS ` +
+ `${getSqlAggregationOverStackAlias(aggregation)}`);
+ }
+
+ aggCols.push(
+ `${aggColPrefix} OVER (PARTITION BY ` +
+ `${partitionByPivotCols.join(', ')}) AS ` +
+ `${getSqlAggregationAlias(aggregation)}`);
+ }
+
+ aggQuery += pivotCols.concat(aggCols).join(',\n ');
+ aggQuery += '\n';
+ aggQuery += 'FROM (\n';
+ aggQuery +=
+ this.generateJoinQuery(pivots, aggregations, whereFilters, joinTables);
+ aggQuery += ')\n';
+ return aggQuery;
+ }
+
+ // Takes a list of pivots and aggregations and generates a query that
+ // extracts all pivots and aggregation partitions and groups by all
+ // columns and orders by each aggregation as requested.
+ private generateQueryImpl(
+ pivots: PivotAttrs[], aggregations: AggregationAttrs[],
+ whereFilters: string[], joinTables: string[], isStackQuery: boolean,
+ orderBy: boolean): string {
+ // No need to generate query if there is no selected pivots or
+ // aggregations.
+ if (pivots.length === 0 && aggregations.length === 0) {
+ return '';
+ }
+
+ let query = '\nSELECT\n';
+
+ const pivotCols = getSqlAliasedPivotColumns(pivots);
+ const aggCols = getSqlAliasedAggregationsColumns(
+ aggregations,
+ /* has_pivots_selected = */ pivots.length > 0,
+ isStackQuery);
+
+ query += pivotCols.concat(aggCols).join(',\n ');
+ query += '\n';
+ query += 'FROM (\n';
+ query += this.generateAggregationQuery(
+ pivots, aggregations, whereFilters, joinTables, isStackQuery);
+ query += ')\n';
+ query += 'GROUP BY ';
+
+ // Grouping by each pivot, additional pivots, and aggregations.
+ const aggregationsGroupBy =
+ aggregations.map(aggregation => getSqlAggregationAlias(aggregation));
+ query += pivotCols.concat(aggregationsGroupBy).join(', ');
+ query += '\n';
+
+ const pivotsOrderBy = [];
+
+ // Sort by depth first if generating a stack query, to ensure that the
+ // parents appear first before their children and allow us to nest the
+ // results into an expandable structure.
+ if (orderBy && isStackQuery) {
+ pivotsOrderBy.push(
+ `${getSqlHiddenPivotAlias(getStackDepthColumn(pivots[0]))} ASC`);
+ }
+
+ // For each aggregation we order by either 'DESC' or 'ASC' as
+ // requested (DESC by default).
+ const orderString = (aggregation: AggregationAttrs) =>
+ `${getSqlAggregationAlias(aggregation)} ` +
+ `${aggregation.order}`;
+ const aggregationsOrderBy =
+ aggregations.map(aggregation => orderString(aggregation));
+
+ if (orderBy && pivotsOrderBy.length + aggregationsOrderBy.length > 0) {
+ query += 'ORDER BY ';
+ query += pivotsOrderBy.concat(aggregationsOrderBy).join(', ');
+ query += '\n';
+ }
+ return query;
+ }
+
+ generateQuery(
+ pivots: PivotAttrs[], aggregations: AggregationAttrs[],
+ whereFilters: string[], joinTables: string[]) {
+ return this.generateQueryImpl(
+ pivots,
+ aggregations,
+ whereFilters,
+ joinTables,
+ /* is_stack_query = */ false,
+ /* order_by = */ true);
+ }
+
+ generateStackQuery(
+ pivots: PivotAttrs[], aggregations: AggregationAttrs[],
+ whereFilters: string[], joinTables: string[], stackId: string) {
+ const stackQuery = this.generateQueryImpl(
+ pivots,
+ aggregations,
+ whereFilters,
+ joinTables,
+ /* is_stack_query = */ true,
+ /* order_by = */ true);
+
+ // Query the next column rows for the parent row.
+ if (pivots.length > 1) {
+ const stackPivot = pivots[0];
+ const currStackQuery = this.generateQueryImpl(
+ pivots,
+ aggregations,
+ whereFilters.concat(getParentStackWhereFilter(stackPivot, stackId)),
+ AVAILABLE_TABLES,
+ /* is_stack_query = */ true,
+ /* order_by = */ false);
+ return `${currStackQuery} UNION ALL ${stackQuery}`;
+ }
+ return stackQuery;
+ }
+}
\ No newline at end of file
diff --git a/ui/src/common/pivot_table_query_generator_unittest.ts b/ui/src/common/pivot_table_query_generator_unittest.ts
new file mode 100644
index 0000000..93681c7
--- /dev/null
+++ b/ui/src/common/pivot_table_query_generator_unittest.ts
@@ -0,0 +1,267 @@
+// 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 {
+ AggregationAttrs,
+ PivotAttrs,
+ SLICE_STACK_COLUMN,
+ WHERE_FILTERS,
+} from './pivot_table_common';
+import {PivotTableQueryGenerator} from './pivot_table_query_generator';
+
+const TABLES = ['slice'];
+
+test('Generate query with pivots and aggregations', () => {
+ const pivotTableQueryGenerator = new PivotTableQueryGenerator();
+ const selectedPivots: PivotAttrs[] = [
+ {tableName: 'slice', columnName: 'type', isStackPivot: false},
+ {tableName: 'slice', columnName: 'id', isStackPivot: false}
+ ];
+ const selectedAggregations: AggregationAttrs[] = [
+ {aggregation: 'SUM', tableName: 'slice', columnName: 'dur', order: 'DESC'}
+ ];
+ const expectedQuery = '\nSELECT\n' +
+ '"slice type",\n' +
+ ' "slice id",\n' +
+ ' "slice dur (SUM)",\n' +
+ ' "slice dur (SUM) (total)"\n' +
+ 'FROM (\n' +
+ 'SELECT\n' +
+ '"slice type",\n' +
+ ' "slice id",\n' +
+ ' SUM("slice dur (SUM)") OVER () AS "slice dur (SUM) (total)",\n' +
+ ' SUM("slice dur (SUM)") OVER (PARTITION BY "slice type", "slice id")' +
+ ' AS "slice dur (SUM)"\n' +
+ 'FROM (\n' +
+ 'SELECT\n' +
+ 'slice.type AS "slice type",\n' +
+ ' slice.id AS "slice id",\n' +
+ ' slice.dur AS "slice dur (SUM)"\n' +
+ 'FROM\n' +
+ 'slice\n' +
+ 'WHERE\n' +
+ 'slice.dur != -1\n' +
+ ')\n' +
+ ')\n' +
+ 'GROUP BY "slice type", "slice id", "slice dur (SUM)"\n' +
+ 'ORDER BY "slice dur (SUM)" DESC\n';
+ expect(pivotTableQueryGenerator.generateQuery(
+ selectedPivots, selectedAggregations, WHERE_FILTERS, TABLES))
+ .toEqual(expectedQuery);
+});
+
+test('Generate query with pivots', () => {
+ const pivotTableQueryGenerator = new PivotTableQueryGenerator();
+ const selectedPivots: PivotAttrs[] = [
+ {tableName: 'slice', columnName: 'type', isStackPivot: false},
+ {tableName: 'slice', columnName: 'id', isStackPivot: false}
+ ];
+ const selectedAggregations: AggregationAttrs[] = [];
+ const expectedQuery = '\nSELECT\n' +
+ '"slice type",\n' +
+ ' "slice id"\n' +
+ 'FROM (\n' +
+ 'SELECT\n' +
+ 'slice.type AS "slice type",\n' +
+ ' slice.id AS "slice id"\n' +
+ 'FROM\n' +
+ 'slice\n' +
+ 'WHERE\n' +
+ 'slice.dur != -1\n' +
+ ')\n' +
+ 'GROUP BY "slice type", "slice id"\n';
+ expect(pivotTableQueryGenerator.generateQuery(
+ selectedPivots, selectedAggregations, WHERE_FILTERS, TABLES))
+ .toEqual(expectedQuery);
+});
+
+test('Generate query with aggregations', () => {
+ const pivotTableQueryGenerator = new PivotTableQueryGenerator();
+ const selectedPivots: PivotAttrs[] = [];
+ const selectedAggregations: AggregationAttrs[] = [
+ {aggregation: 'SUM', tableName: 'slice', columnName: 'dur', order: 'DESC'},
+ {aggregation: 'MAX', tableName: 'slice', columnName: 'dur', order: 'ASC'}
+ ];
+ const expectedQuery = '\nSELECT\n' +
+ '"slice dur (SUM)",\n' +
+ ' "slice dur (MAX)"\n' +
+ 'FROM (\n' +
+ 'SELECT\n' +
+ 'SUM("slice dur (SUM)") AS "slice dur (SUM)",\n' +
+ ' MAX("slice dur (MAX)") AS "slice dur (MAX)"\n' +
+ 'FROM (\n' +
+ 'SELECT\n' +
+ 'slice.dur AS "slice dur (SUM)",\n' +
+ ' slice.dur AS "slice dur (MAX)"\n' +
+ 'FROM\n' +
+ 'slice\n' +
+ 'WHERE\n' +
+ 'slice.dur != -1\n' +
+ ')\n' +
+ ')\n' +
+ 'GROUP BY "slice dur (SUM)", "slice dur (MAX)"\n' +
+ 'ORDER BY "slice dur (SUM)" DESC, "slice dur (MAX)" ASC\n';
+ expect(pivotTableQueryGenerator.generateQuery(
+ selectedPivots, selectedAggregations, WHERE_FILTERS, TABLES))
+ .toEqual(expectedQuery);
+});
+
+test('Generate a query with stack pivot', () => {
+ const pivotTableQueryGenerator = new PivotTableQueryGenerator();
+ const selectedPivots: PivotAttrs[] = [
+ {tableName: 'slice', columnName: SLICE_STACK_COLUMN, isStackPivot: true},
+ {tableName: 'slice', columnName: 'category', isStackPivot: false}
+ ];
+ const selectedAggregations: AggregationAttrs[] = [
+ {aggregation: 'COUNT', tableName: 'slice', columnName: 'id', order: 'DESC'},
+ ];
+ const expectedQuery = '\nSELECT\n' +
+ '"slice name (stack)",\n' +
+ ' "slice depth (hidden)",\n' +
+ ' "slice stack_id (hidden)",\n' +
+ ' "slice parent_stack_id (hidden)",\n' +
+ ' "slice category",\n' +
+ ' "slice id (COUNT)",\n' +
+ ' "slice id (COUNT) (total)"\n' +
+ 'FROM (\n' +
+ 'SELECT\n' +
+ '"slice name (stack)",\n' +
+ ' "slice depth (hidden)",\n' +
+ ' "slice stack_id (hidden)",\n' +
+ ' "slice parent_stack_id (hidden)",\n' +
+ ' "slice category",\n' +
+ ' COUNT("slice id (COUNT)") OVER () AS "slice id (COUNT) (total)",\n' +
+ ' COUNT("slice id (COUNT)") OVER (PARTITION BY' +
+ ' "slice stack_id (hidden)", "slice category") AS "slice id (COUNT)"\n' +
+ 'FROM (\n' +
+ 'SELECT\n' +
+ 'slice.name AS "slice name (stack)",\n' +
+ ' slice.depth AS "slice depth (hidden)",\n' +
+ ' slice.stack_id AS "slice stack_id (hidden)",\n' +
+ ' slice.parent_stack_id AS "slice parent_stack_id (hidden)",\n' +
+ ' slice.category AS "slice category",\n' +
+ ' slice.id AS "slice id (COUNT)"\n' +
+ 'FROM\n' +
+ 'slice\n' +
+ 'WHERE\n' +
+ 'slice.dur != -1\n' +
+ ')\n' +
+ ')\n' +
+ 'GROUP BY "slice name (stack)", "slice depth (hidden)", ' +
+ '"slice stack_id (hidden)", "slice parent_stack_id (hidden)", ' +
+ '"slice category", "slice id (COUNT)"\n' +
+ 'ORDER BY "slice id (COUNT)" DESC\n';
+ expect(pivotTableQueryGenerator.generateQuery(
+ selectedPivots, selectedAggregations, WHERE_FILTERS, TABLES))
+ .toEqual(expectedQuery);
+});
+
+test('Generate a descendant stack query', () => {
+ const pivotTableQueryGenerator = new PivotTableQueryGenerator();
+ const selectedPivots: PivotAttrs[] = [
+ {tableName: 'slice', columnName: SLICE_STACK_COLUMN, isStackPivot: true},
+ ];
+ const selectedAggregations: AggregationAttrs[] = [];
+ const expectedQuery = '\nSELECT\n' +
+ '"slice name (stack)",\n' +
+ ' "slice depth (hidden)",\n' +
+ ' "slice stack_id (hidden)",\n' +
+ ' "slice parent_stack_id (hidden)"\n' +
+ 'FROM (\n' +
+ 'SELECT\n' +
+ 'slice.name AS "slice name (stack)",\n' +
+ ' slice.depth AS "slice depth (hidden)",\n' +
+ ' slice.stack_id AS "slice stack_id (hidden)",\n' +
+ ' slice.parent_stack_id AS "slice parent_stack_id (hidden)"\n' +
+ 'FROM\n' +
+ 'descendant_slice_by_stack(stack_id) AS slice\n' +
+ 'WHERE\n' +
+ 'slice.dur != -1\n' +
+ ')\n' +
+ 'GROUP BY "slice name (stack)", "slice depth (hidden)", ' +
+ '"slice stack_id (hidden)", "slice parent_stack_id (hidden)"\n' +
+ 'ORDER BY "slice depth (hidden)" ASC\n';
+
+ const table = ['descendant_slice_by_stack(stack_id) AS slice'];
+ expect(pivotTableQueryGenerator.generateStackQuery(
+ selectedPivots,
+ selectedAggregations,
+ WHERE_FILTERS,
+ table,
+ /* stack_id = */ 'stack_id'))
+ .toEqual(expectedQuery);
+});
+
+test('Generate a descendant stack query with another pivot', () => {
+ const pivotTableQueryGenerator = new PivotTableQueryGenerator();
+ const selectedPivots: PivotAttrs[] = [
+ {tableName: 'slice', columnName: SLICE_STACK_COLUMN, isStackPivot: true},
+ {tableName: 'slice', columnName: 'category', isStackPivot: false}
+ ];
+ const selectedAggregations: AggregationAttrs[] = [];
+ const expectedQuery = '\nSELECT\n' +
+ '"slice name (stack)",\n' +
+ ' "slice depth (hidden)",\n' +
+ ' "slice stack_id (hidden)",\n' +
+ ' "slice parent_stack_id (hidden)",\n' +
+ ' "slice category"\n' +
+ 'FROM (\n' +
+ 'SELECT\n' +
+ 'slice.name AS "slice name (stack)",\n' +
+ ' slice.depth AS "slice depth (hidden)",\n' +
+ ' slice.stack_id AS "slice stack_id (hidden)",\n' +
+ ' slice.parent_stack_id AS "slice parent_stack_id (hidden)",\n' +
+ ' slice.category AS "slice category"\n' +
+ 'FROM\n' +
+ 'slice\n' +
+ 'WHERE\n' +
+ 'slice.dur != -1 AND\n' +
+ ' slice.stack_id = stack_id\n' +
+ ')\n' +
+ 'GROUP BY "slice name (stack)", "slice depth (hidden)", ' +
+ '"slice stack_id (hidden)", "slice parent_stack_id (hidden)", ' +
+ '"slice category"\n' +
+ ' UNION ALL \n' +
+ 'SELECT\n' +
+ '"slice name (stack)",\n' +
+ ' "slice depth (hidden)",\n' +
+ ' "slice stack_id (hidden)",\n' +
+ ' "slice parent_stack_id (hidden)",\n' +
+ ' "slice category"\n' +
+ 'FROM (\n' +
+ 'SELECT\n' +
+ 'slice.name AS "slice name (stack)",\n' +
+ ' slice.depth AS "slice depth (hidden)",\n' +
+ ' slice.stack_id AS "slice stack_id (hidden)",\n' +
+ ' slice.parent_stack_id AS "slice parent_stack_id (hidden)",\n' +
+ ' slice.category AS "slice category"\n' +
+ 'FROM\n' +
+ 'descendant_slice_by_stack(stack_id) AS slice\n' +
+ 'WHERE\n' +
+ 'slice.dur != -1\n' +
+ ')\n' +
+ 'GROUP BY "slice name (stack)", "slice depth (hidden)", ' +
+ '"slice stack_id (hidden)", "slice parent_stack_id (hidden)", ' +
+ '"slice category"\n' +
+ 'ORDER BY "slice depth (hidden)" ASC\n';
+
+ const table = ['descendant_slice_by_stack(stack_id) AS slice'];
+ expect(pivotTableQueryGenerator.generateStackQuery(
+ selectedPivots,
+ selectedAggregations,
+ WHERE_FILTERS,
+ table,
+ /* stack_id = */ 'stack_id'))
+ .toEqual(expectedQuery);
+});
diff --git a/ui/src/common/protos.ts b/ui/src/common/protos.ts
index 832c838..ea3c3fb 100644
--- a/ui/src/common/protos.ts
+++ b/ui/src/common/protos.ts
@@ -13,7 +13,6 @@
// limitations under the License.
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
@@ -46,75 +45,11 @@
import VmstatCounters = protos.perfetto.protos.VmstatCounters;
// Trace Processor protos.
-import IRawQueryArgs = protos.perfetto.protos.IRawQueryArgs;
import QueryArgs = protos.perfetto.protos.QueryArgs;
-import RawQueryArgs = protos.perfetto.protos.RawQueryArgs;
-import RawQueryResult = protos.perfetto.protos.RawQueryResult;
import StatusResult = protos.perfetto.protos.StatusResult;
import ComputeMetricArgs = protos.perfetto.protos.ComputeMetricArgs;
import ComputeMetricResult = protos.perfetto.protos.ComputeMetricResult;
-// TODO(hjd): Maybe these should go in their own file.
-export interface Row { [key: string]: number|string; }
-
-const COLUMN_TYPE_STR = RawQueryResult.ColumnDesc.Type.STRING;
-const COLUMN_TYPE_DOUBLE = RawQueryResult.ColumnDesc.Type.DOUBLE;
-const COLUMN_TYPE_LONG = RawQueryResult.ColumnDesc.Type.LONG;
-
-function getCell(result: RawQueryResult, column: number, row: number): number|
- string|null {
- const values = result.columns[column];
- if (values.isNulls![row]) return null;
- switch (result.columnDescriptors[column].type) {
- case COLUMN_TYPE_LONG:
- return +values.longValues![row];
- case COLUMN_TYPE_DOUBLE:
- return +values.doubleValues![row];
- case COLUMN_TYPE_STR:
- return values.stringValues![row];
- default:
- throw new Error('Unhandled type!');
- }
-}
-
-export function rawQueryResultColumns(result: RawQueryResult): string[] {
- // Two columns can conflict on the same name, e.g.
- // select x.foo, y.foo from x join y. In that case store them using the
- // full table.column notation.
- const res = [] as string[];
- const uniqColNames = new Set<string>();
- const colNamesToDedupe = new Set<string>();
- for (const col of result.columnDescriptors) {
- const colName = col.name || '';
- if (uniqColNames.has(colName)) {
- colNamesToDedupe.add(colName);
- }
- uniqColNames.add(colName);
- }
- for (let i = 0; i < result.columnDescriptors.length; i++) {
- const colName = result.columnDescriptors[i].name || '';
- if (colNamesToDedupe.has(colName)) {
- res.push(`${colName}.${i + 1}`);
- } else {
- res.push(colName);
- }
- }
- return res;
-}
-
-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++) {
- const row: Row = {};
- for (const [name, colNum] of columns) {
- const cell = getCell(result, colNum, rowNum);
- row[name] = cell === null ? '[NULL]' : cell;
- }
- yield row;
- }
-}
-
export {
AndroidLogConfig,
AndroidLogId,
@@ -131,7 +66,6 @@
IAndroidPowerConfig,
IBufferConfig,
IProcessStatsConfig,
- IRawQueryArgs,
ISysStatsConfig,
ITraceConfig,
JavaContinuousDumpConfig,
@@ -140,8 +74,6 @@
NativeContinuousDumpConfig,
ProcessStatsConfig,
QueryArgs,
- RawQueryArgs,
- RawQueryResult,
StatCounters,
StatusResult,
SysStatsConfig,
diff --git a/ui/src/common/queries.ts b/ui/src/common/queries.ts
index 8ad01b6..1e7e671 100644
--- a/ui/src/common/queries.ts
+++ b/ui/src/common/queries.ts
@@ -12,7 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {Row} from './protos';
+import {Engine} from './engine';
+import {Row} from './query_result';
+
+const MAX_DISPLAY_ROWS = 10000;
export interface QueryResponse {
id: string;
@@ -23,3 +26,48 @@
columns: string[];
rows: Row[];
}
+
+export async function runQuery(
+ queryId: string, sqlQuery: string, engine: Engine): Promise<QueryResponse> {
+ const startMs = performance.now();
+ const queryRes = engine.query(sqlQuery);
+
+ // TODO(primiano): once the controller thread is gone we should pass down
+ // the result objects directly to the frontend, iterate over the result
+ // and deal with pagination there. For now we keep the old behavior and
+ // truncate to 10k rows.
+
+ try {
+ await queryRes.waitAllRows();
+ } catch {
+ // In the case of a query error we don't want the exception to bubble up
+ // as a crash. The |queryRes| object will be populated anyways.
+ // queryRes.error() is used to tell if the query errored or not. If it
+ // errored, the frontend will show a graceful message instead.
+ }
+
+ const durationMs = performance.now() - startMs;
+ const rows: Row[] = [];
+ const columns = queryRes.columns();
+ let numRows = 0;
+ for (const iter = queryRes.iter({}); iter.valid(); iter.next()) {
+ const row: Row = {};
+ for (const colName of columns) {
+ const value = iter.get(colName);
+ row[colName] = value === null ? 'NULL' : value;
+ }
+ rows.push(row);
+ if (++numRows >= MAX_DISPLAY_ROWS) break;
+ }
+
+ const result: QueryResponse = {
+ id: queryId,
+ query: sqlQuery,
+ durationMs,
+ error: queryRes.error(),
+ totalRowCount: queryRes.numRows(),
+ columns,
+ rows,
+ };
+ return result;
+}
\ No newline at end of file
diff --git a/ui/src/common/query_iterator.ts b/ui/src/common/query_iterator.ts
deleted file mode 100644
index 8e1fa81..0000000
--- a/ui/src/common/query_iterator.ts
+++ /dev/null
@@ -1,261 +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';
-
-// These types are used both for the new streaming query iterator and the old
-// columnar RawQueryResult.
-
-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 = string|number|null;
-
-// One row extracted from an SQL result:
-export interface Row {
- [key: string]: ColumnType;
-}
-
-// The methods that any iterator has to implement.
-export interface RowIteratorBase {
- valid(): boolean;
- next(): void;
-}
-
-// A RowIterator is a type that has all the fields defined in the query spec
-// plus the valid() and next() operators. This is to ultimately allow the
-// clients to do:
-// const result = await engine.queryV2("select name, surname, id from people;");
-// const iter = queryResult.iter({name: STR, surname: STR, id: NUM});
-// for (; iter.valid(); iter.next())
-// console.log(iter.name, iter.surname);
-export type RowIterator<T extends Row> = RowIteratorBase&T;
-
-// The old iterator for non-batched queries. Going away. Usage.
-// const result = await engine.query("select 42 as n;");
-// const it = getRowIterator({"answer": NUM}, result);
-// for (; it.valid(); it.next()) {
-// console.log(it.row.answer);
-// }
-export interface LegacyRowIterator<T extends Row> {
- valid(): boolean;
- next(): void;
- row: T;
-}
-
-export function columnTypeToString(t: ColumnType): string {
- switch (t) {
- case NUM:
- return 'NUM';
- case NUM_NULL:
- return 'NUM_NULL';
- case STR:
- return 'STR';
- case STR_NULL:
- return 'STR_NULL';
- default:
- return `INVALID(${t})`;
- }
-}
-
-// TODO(primiano): the types and helpers in the rest of this file are
-// transitional and will be removed once we migrate everything to the streaming
-// query API.
-
-// Exported for testing
-export function findColumnIndex(
- result: RawQueryResult, name: string, columnType: ColumnType): 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): LegacyRowIterator<T> {
- const iter = new ColumnarRowIterator(querySpec, queryResult);
- return iter as unknown as LegacyRowIterator<T>;
-}
-
-// Deliberately not exported, use iterUntyped() below to make code easy to
-// switch to other queryResult formats.
-function iterUntypedFromColumns(result: RawQueryResult):
- LegacyRowIterator<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 LegacyRowIterator<Row>;
-}
-
-export function iterUntyped(result: RawQueryResult): LegacyRowIterator<Row> {
- return iterUntypedFromColumns(result);
-}
-
-export function iter<T extends Row>(
- spec: T, result: RawQueryResult): LegacyRowIterator<T> {
- return iterFromColumns(spec, result);
-}
-
-export function slowlyCountRows(result: RawQueryResult): number {
- // This isn't actually slow for columnar data but it might be for other
- // formats.
- return +result.numRecords;
-}
-
-export function singleRow<T extends Row>(spec: T, result: RawQueryResult): 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: RawQueryResult): 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/query_result.ts b/ui/src/common/query_result.ts
index 82afc75..70186cf 100644
--- a/ui/src/common/query_result.ts
+++ b/ui/src/common/query_result.ts
@@ -22,7 +22,7 @@
// The classes in this file are organized as follows:
//
// QueryResultImpl:
-// The object returned by the Engine.queryV2(sql) method.
+// The object returned by the Engine.query(sql) method.
// This object is a holder of row data. Batches of raw get appended
// incrementally as they are received by the remote TraceProcessor instance.
// QueryResultImpl also deals with asynchronicity of queries and allows callers
@@ -53,16 +53,58 @@
import {assertExists, assertFalse, assertTrue} from '../base/logging';
import {utf8Decode} from '../base/string_utils';
-import {
- columnTypeToString,
- NUM,
- NUM_NULL,
- Row,
- RowIterator,
- RowIteratorBase,
- STR,
- STR_NULL
-} from './query_iterator';
+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 = string|number|null;
+
+export class QueryError extends Error {}
+
+// One row extracted from an SQL result:
+export interface Row {
+ [key: string]: ColumnType;
+}
+
+// The methods that any iterator has to implement.
+export interface RowIteratorBase {
+ valid(): boolean;
+ next(): void;
+
+ // Reflection support for cases where the column names are not known upfront
+ // (e.g. the query result table for user-provided SQL queries).
+ // It throws if the passed column name doesn't exist.
+ // Example usage:
+ // for (const it = queryResult.iter({}); it.valid(); it.next()) {
+ // for (const columnName : queryResult.columns()) {
+ // console.log(it.get(columnName));
+ get(columnName: string): ColumnType;
+}
+
+// A RowIterator is a type that has all the fields defined in the query spec
+// plus the valid() and next() operators. This is to ultimately allow the
+// clients to do:
+// const result = await engine.query("select name, surname, id from people;");
+// const iter = queryResult.iter({name: STR, surname: STR, id: NUM});
+// for (; iter.valid(); iter.next())
+// console.log(iter.name, iter.surname);
+export type RowIterator<T extends Row> = RowIteratorBase&T;
+
+function columnTypeToString(t: ColumnType): string {
+ switch (t) {
+ case NUM:
+ return 'NUM';
+ case NUM_NULL:
+ return 'NUM_NULL';
+ case STR:
+ return 'STR';
+ case STR_NULL:
+ return 'STR_NULL';
+ default:
+ return `INVALID(${t})`;
+ }
+}
// Disable Long.js support in protobuf. This seems to be enabled only in tests
// but not in production code. In any case, for now we want casting to number
@@ -123,6 +165,10 @@
// have been fetched. The promise return value is always the object iself.
waitAllRows(): Promise<QueryResult>;
+ // Can return an empty array if called before the first batch is resolved.
+ // This should be called only after having awaited for at least one batch.
+ columns(): string[];
+
// TODO(primiano): next CLs will introduce a waitMoreRows() to allow tracks
// to await until some more data (but not necessarily all) is available. For
// now everything uses waitAllRows().
@@ -132,7 +178,7 @@
export interface WritableQueryResult extends QueryResult {
// |resBytes| is a proto-encoded trace_processor.QueryResult message.
// The overall flow looks as follows:
- // - The user calls engine.queryV2('select ...') and gets a QueryResult back.
+ // - The user calls engine.query('select ...') and gets a QueryResult back.
// - The query call posts a message to the worker that runs the SQL engine (
// or sends a HTTP request in case of the RPC+HTTP interface).
// - The returned QueryResult object is initially empty.
@@ -178,6 +224,9 @@
error(): string|undefined {
return this._error;
}
+ columns(): string[] {
+ return this.columnNames;
+ }
iter<T extends Row>(spec: T): RowIterator<T> {
const impl = new RowIteratorImplWithRowData(spec, this);
@@ -213,6 +262,7 @@
const reader = protobuf.Reader.create(resBytes);
assertTrue(reader.pos === 0);
const columnNamesEmptyAtStartOfBatch = this.columnNames.length === 0;
+ const columnNamesSet = new Set<string>();
while (reader.pos < reader.len) {
const tag = reader.uint32();
switch (tag >>> 3) {
@@ -220,7 +270,20 @@
// Only the first batch should contain the column names. If this fires
// something is going wrong in the handling of the batch stream.
assertTrue(columnNamesEmptyAtStartOfBatch);
- this.columnNames.push(reader.string());
+ const origColName = reader.string();
+ let colName = origColName;
+ // In some rare cases two columns can have the same name (b/194891824)
+ // e.g. `select 1 as x, 2 as x`. These queries don't happen in the
+ // UI code, but they can happen when the user types a query (e.g.
+ // with a join). The most practical thing we can do here is renaming
+ // the columns with a suffix. Keeping the same name will break when
+ // iterating, because column names become iterator object keys.
+ for (let i = 1; columnNamesSet.has(colName); ++i) {
+ colName = `${origColName}_${i}`;
+ assertTrue(i < 100); // Give up at some point;
+ }
+ columnNamesSet.add(colName);
+ this.columnNames.push(colName);
break;
case 2: // error
// The query has errored only if the |error| field is non-empty.
@@ -274,7 +337,7 @@
if (this._error === undefined) {
promise.resolve(arg);
} else {
- promise.reject(new Error(this._error));
+ promise.reject(new QueryError(this._error));
}
}
}
@@ -449,6 +512,17 @@
return this.isValid;
}
+
+ get(columnName: string): ColumnType {
+ const res = this.rowData[columnName];
+ if (res === undefined) {
+ throw new Error(
+ `Column '${columnName}' doesn't exist. ` +
+ `Actual columns: [${this.columnNames.join(',')}]`);
+ }
+ return res;
+ }
+
// Moves the cursor next by one row and updates |isValid|.
// When this fails to move, two cases are possible:
// 1. We reached the end of the result set (this is the case if
@@ -551,40 +625,48 @@
// Check that the cells types are consistent.
const numColumns = this.numColumns;
- if (numColumns === 0) {
- assertTrue(batch.numCells === 0);
- } else {
- for (let i = this.nextCellTypeOff; i < this.cellTypesEnd; i++) {
- const col = (i - this.nextCellTypeOff) % numColumns;
- const colName = this.columnNames[col];
- const actualType = this.batchBytes[i] as CellType;
- const expType = this.rowSpec[colName];
+ if (batch.numCells === 0) {
+ // This can happen if the query result contains just an error. In this
+ // an empty batch with isLastBatch=true is appended as an EOF marker.
+ // In theory TraceProcessor could return an empty batch in the middle and
+ // that would be fine from a protocol viewpoint. In practice, no code path
+ // does that today so it doesn't make sense trying supporting it with a
+ // recursive call to tryMoveToNextBatch().
+ assertTrue(batch.isLastBatch);
+ return false;
+ }
- // If undefined, the caller doesn't want to read this column at all, so
- // it can be whatever.
- if (expType === undefined) continue;
+ assertTrue(numColumns > 0);
+ for (let i = this.nextCellTypeOff; i < this.cellTypesEnd; i++) {
+ const col = (i - this.nextCellTypeOff) % numColumns;
+ const colName = this.columnNames[col];
+ const actualType = this.batchBytes[i] as CellType;
+ const expType = this.rowSpec[colName];
- let err = '';
- if (actualType === CellType.CELL_NULL &&
- (expType !== STR_NULL && expType !== NUM_NULL)) {
- err = 'SQL value is NULL but that was not expected' +
- ` (expected type: ${columnTypeToString(expType)}).` +
- 'Did you intend to use NUM_NULL or STRING_NULL?';
- } else if (
- ((actualType === CellType.CELL_VARINT ||
- actualType === CellType.CELL_FLOAT64) &&
- (expType !== NUM && expType !== NUM_NULL)) ||
- ((actualType === CellType.CELL_STRING) &&
- (expType !== STR && expType !== STR_NULL))) {
- err = `Incompatible cell type. Expected: ${
- columnTypeToString(
- expType)} actual: ${CELL_TYPE_NAMES[actualType]}`;
- }
- if (err.length > 0) {
- throw new Error(
- `Error @ row: ${Math.floor(i / numColumns)} col: '` +
- `${colName}': ${err}`);
- }
+ // If undefined, the caller doesn't want to read this column at all, so
+ // it can be whatever.
+ if (expType === undefined) continue;
+
+ let err = '';
+ if (actualType === CellType.CELL_NULL &&
+ (expType !== STR_NULL && expType !== NUM_NULL)) {
+ err = 'SQL value is NULL but that was not expected' +
+ ` (expected type: ${columnTypeToString(expType)}). ` +
+ 'Did you intend to use NUM_NULL or STR_NULL?';
+ } else if (
+ ((actualType === CellType.CELL_VARINT ||
+ actualType === CellType.CELL_FLOAT64) &&
+ (expType !== NUM && expType !== NUM_NULL)) ||
+ ((actualType === CellType.CELL_STRING) &&
+ (expType !== STR && expType !== STR_NULL))) {
+ err = `Incompatible cell type. Expected: ${
+ columnTypeToString(
+ expType)} actual: ${CELL_TYPE_NAMES[actualType]}`;
+ }
+ if (err.length > 0) {
+ throw new Error(
+ `Error @ row: ${Math.floor(i / numColumns)} col: '` +
+ `${colName}': ${err}`);
}
}
return true;
@@ -601,6 +683,7 @@
next: () => void;
valid: () => boolean;
+ get: (columnName: string) => ColumnType;
constructor(querySpec: Row, res: QueryResultImpl) {
const thisAsRow = this as {} as Row;
@@ -608,6 +691,7 @@
this._impl = new RowIteratorImpl(querySpec, thisAsRow, res);
this.next = this._impl.next.bind(this._impl);
this.valid = this._impl.valid.bind(this._impl);
+ this.get = this._impl.get.bind(this._impl);
}
}
@@ -638,6 +722,9 @@
numRows() {
return this.impl.numRows();
}
+ columns() {
+ return this.impl.columns();
+ }
error() {
return this.impl.error();
}
diff --git a/ui/src/common/query_result_unittest.ts b/ui/src/common/query_result_unittest.ts
index bacf480..2b95c0b 100644
--- a/ui/src/common/query_result_unittest.ts
+++ b/ui/src/common/query_result_unittest.ts
@@ -14,8 +14,7 @@
import * as protoNamespace from '../gen/protos';
-import {NUM, NUM_NULL, STR, STR_NULL} from './query_iterator';
-import {createQueryResult} from './query_result';
+import {createQueryResult, NUM, NUM_NULL, STR, STR_NULL} from './query_result';
const T = protoNamespace.perfetto.protos.QueryResult.CellsBatch.CellType;
const QueryResultProto = protoNamespace.perfetto.protos.QueryResult;
@@ -189,7 +188,7 @@
test('QueryResult.EarlyError', () => {
const resProto = QueryResultProto.create({
- columnNames: ['n', 's'],
+ columnNames: [],
batch: [{isLastBatch: true}],
error: 'Oh dear, this SQL query is too complicated, I give up',
});
@@ -197,6 +196,8 @@
qr.appendResultBatch(QueryResultProto.encode(resProto).finish());
expect(qr.error()).toContain('Oh dear');
expect(qr.isComplete()).toBe(true);
+ const iter = qr.iter({});
+ expect(iter.valid()).toBe(false);
});
test('QueryResult.LateError', () => {
@@ -258,3 +259,44 @@
expect(awaitRes.numRows()).toBe(2);
expect(qr.numRows()).toBe(2);
});
+
+
+// Regression test for b/194891824 .
+test('QueryResult.DuplicateColumnNames', () => {
+ const batch = QueryResultProto.CellsBatch.create({
+ cells: [
+ T.CELL_VARINT,
+ T.CELL_STRING,
+ T.CELL_FLOAT64,
+ T.CELL_STRING,
+ T.CELL_STRING
+ ],
+ varintCells: [42],
+ stringCells: ['a', 'b', 'c'].join('\0'),
+ float64Cells: [4.2],
+ isLastBatch: true,
+ });
+ const resProto = QueryResultProto.create({
+ columnNames: ['x', 'y', 'x', 'x', 'y'],
+ batch: [batch],
+ });
+
+ const qr = createQueryResult();
+ qr.appendResultBatch(QueryResultProto.encode(resProto).finish());
+ expect(qr.isComplete()).toBe(true);
+ expect(qr.numRows()).toBe(1);
+ expect(qr.columns()).toEqual(['x', 'y', 'x_1', 'x_2', 'y_1']);
+ // First try iterating without selecting any column.
+ {
+ const iter = qr.iter({x: NUM, y: STR, x_1: NUM, x_2: STR, y_1: STR});
+ expect(iter.valid()).toBe(true);
+ expect(iter.x).toBe(42);
+ expect(iter.y).toBe('a');
+ expect(iter.x_1).toBe(4.2);
+ expect(iter.x_2).toBe('b');
+ expect(iter.y_1).toBe('c');
+ iter.next();
+ expect(iter.valid()).toBe(false);
+ }
+ expect(() => qr.iter({x_3: NUM})).toThrowError(/\bx_3\b.*not found/);
+});
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 e38f4b2..2905967 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -12,6 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {validateRecordConfig} from '../controller/validate_config';
+import {
+ AggregationAttrs,
+ PivotAttrs,
+ SubQueryAttrs,
+ TableAttrs
+} from './pivot_table_common';
+
/**
* A plain js object, holding objects of type |Class| keyed by string id.
* We use this instead of using |Map| object since it is simpler and faster to
@@ -23,8 +31,9 @@
[P in keyof T]: T[P];
}&{lastUpdate: number};
-export type OmniboxState =
- Timestamped<{omnibox: string; mode: 'SEARCH' | 'COMMAND'}>;
+export type OmniboxMode = 'SEARCH'|'COMMAND';
+
+export type OmniboxState = Timestamped<{omnibox: string; mode: OmniboxMode}>;
export type VisibleState =
Timestamped<{startSec: number; endSec: number; resolution: number;}>;
@@ -52,7 +61,12 @@
export const MAX_TIME = 180;
// 3: TrackKindPriority and related sorting changes.
-export const STATE_VERSION = 3;
+// 5: Move a large number of items off frontendLocalState and onto state.
+// 6: Common PivotTableConfig and pivot table specific PivotTableState.
+// 7: Split Chrome categories in two and add 'symbolize ksyms' flag.
+// 8: Rename several variables
+// "[...]HeapProfileFlamegraph[...]" -> "[...]Flamegraph[...]".
+export const STATE_VERSION = 8;
export const SCROLLING_TRACK_GROUP = 'ScrollingTracks';
@@ -67,8 +81,8 @@
'ORDINARY' = 3
}
-export type HeapProfileFlamegraphViewingOption =
- 'SPACE'|'ALLOC_SPACE'|'OBJECTS'|'ALLOC_OBJECTS';
+export type FlamegraphStateViewingOption =
+ 'SPACE'|'ALLOC_SPACE'|'OBJECTS'|'ALLOC_OBJECTS'|'PERF_SAMPLES';
export interface CallsiteInfo {
id: number;
@@ -90,10 +104,20 @@
export interface TraceArrayBufferSource {
type: 'ARRAY_BUFFER';
+ buffer: ArrayBuffer;
title: string;
url?: string;
fileName?: string;
- buffer: ArrayBuffer;
+
+ // |uuid| is set only when loading from the cache via ?trace_id=123. When set,
+ // this matches global.state.traceUuid, with the exception of the following
+ // time window: When a trace T1 is loaded and the user loads another trace T2,
+ // this |uuid| will be == T2, but the globals.state.traceUuid will be
+ // temporarily == T1 until T2 has been loaded (consistently to what happens
+ // with all other state fields).
+ uuid?: string;
+ // if |localOnly| is true then the trace should not be shared or downloaded.
+ localOnly?: boolean;
}
export interface TraceUrlSource {
@@ -163,7 +187,7 @@
}
export interface Note {
- noteType: 'DEFAULT'|'MOVIE';
+ noteType: 'DEFAULT';
id: string;
timestamp: number;
color: string;
@@ -203,13 +227,21 @@
type: string;
}
-export interface HeapProfileFlamegraph {
- kind: 'HEAP_PROFILE_FLAMEGRAPH';
+export interface PerfSamplesSelection {
+ kind: 'PERF_SAMPLES';
id: number;
upid: number;
ts: number;
type: string;
- viewingOption: HeapProfileFlamegraphViewingOption;
+}
+
+export interface FlamegraphState {
+ kind: 'FLAMEGRAPH_STATE';
+ id: number;
+ upid: number;
+ ts: number;
+ type: string;
+ viewingOption: FlamegraphStateViewingOption;
focusRegex: string;
expandedCallsite?: CallsiteInfo;
}
@@ -235,7 +267,7 @@
type Selection =
(NoteSelection|SliceSelection|CounterSelection|HeapProfileSelection|
CpuProfileSampleSelection|ChromeSliceSelection|ThreadStateSelection|
- AreaSelection)&{trackId?: string};
+ AreaSelection|PerfSamplesSelection)&{trackId?: string};
export interface LogsPagination {
offset: number;
@@ -267,11 +299,27 @@
requestedMetric?: string; // Unset after metric request is handled.
}
+export interface PivotTableConfig {
+ availableColumns?: TableAttrs[]; // Undefined until list is loaded.
+ availableAggregations?: string[]; // Undefined until list is loaded.
+}
+
+export interface PivotTableState {
+ id: string;
+ name: string;
+ selectedPivots: PivotAttrs[];
+ selectedAggregations: AggregationAttrs[];
+ requestedAction?: // Unset after pivot table column request is handled.
+ {action: string, attrs?: SubQueryAttrs};
+ isLoadingQuery: boolean;
+ traceTime?: TraceTime;
+ selectedTrackIds?: number[];
+}
+
export interface State {
// tslint:disable-next-line:no-any
[key: string]: any;
version: number;
- route: string|null;
nextId: number;
nextNoteId: number;
nextAreaId: number;
@@ -288,6 +336,7 @@
newEngineMode: NewEngineMode;
engines: ObjectById<EngineConfig>;
traceTime: TraceTime;
+ traceUuid?: string;
trackGroups: ObjectById<TrackGroupState>;
tracks: ObjectById<TrackState>;
areas: ObjectById<AreaById>;
@@ -303,9 +352,11 @@
notes: ObjectById<Note|AreaNote>;
status: Status;
currentSelection: Selection|null;
- currentHeapProfileFlamegraph: HeapProfileFlamegraph|null;
+ currentFlamegraphState: FlamegraphState|null;
logsPagination: LogsPagination;
traceConversionInProgress: boolean;
+ pivotTableConfig: PivotTableConfig;
+ pivotTable: ObjectById<PivotTableState>;
/**
* This state is updated on the frontend at 60Hz and eventually syncronised to
@@ -315,12 +366,23 @@
*/
frontendLocalState: FrontendLocalState;
- video: string | null;
- videoEnabled: boolean;
- videoOffset: number;
- videoNoteIds: string[];
- scrubbingEnabled: boolean;
- flagPauseEnabled: boolean;
+ // Show track perf debugging overlay
+ perfDebug: boolean;
+
+ // Show the sidebar extended
+ sidebarVisible: boolean;
+
+ // Hovered and focused events
+ hoveredUtid: number;
+ hoveredPid: number;
+ hoveredLogsTimestamp: number;
+ hoveredNoteTimestamp: number;
+ highlightedSliceId: number;
+ focusedFlowIdLeft: number;
+ focusedFlowIdRight: number;
+
+ searchIndex: number;
+ currentTab?: string;
/**
* Trace recording
@@ -371,13 +433,13 @@
export function isAdbTarget(target: RecordingTarget):
target is AdbRecordingTarget {
- if ((target as AdbRecordingTarget).serial) return true;
- return false;
+ return !!(target as AdbRecordingTarget).serial;
}
export function hasActiveProbes(config: RecordConfig) {
const fieldsWithEmptyResult = new Set<string>(['hpBlockClient']);
- for (const key in config) {
+ let key: keyof RecordConfig;
+ for (key in config) {
if (typeof (config[key]) === 'boolean' && config[key] === true &&
!fieldsWithEmptyResult.has(key)) {
return true;
@@ -387,8 +449,6 @@
}
export interface RecordConfig {
- [key: string]: null|number|boolean|string|string[];
-
// Global settings
mode: RecordMode;
durationMs: number;
@@ -402,8 +462,6 @@
cpuCoarsePollMs: number;
cpuSyscall: boolean;
- screenRecord: boolean;
-
gpuFreq: boolean;
gpuMemTotal: boolean;
@@ -451,74 +509,22 @@
procStatsPeriodMs: number;
chromeCategoriesSelected: string[];
+ chromeHighOverheadCategoriesSelected: string[];
+
+ chromeLogs: boolean;
+ taskScheduling: boolean;
+ ipcFlows: boolean;
+ jsExecution: boolean;
+ webContentRendering: boolean;
+ uiRendering: boolean;
+ inputEvents: boolean;
+ navigationAndLoading: boolean;
+
+ symbolizeKsyms: boolean;
}
export function createEmptyRecordConfig(): RecordConfig {
- return {
- mode: 'STOP_WHEN_FULL',
- durationMs: 10000.0,
- maxFileSizeMb: 100,
- fileWritePeriodMs: 2500,
- bufferSizeMb: 64.0,
-
- cpuSched: false,
- cpuFreq: false,
- cpuSyscall: false,
-
- screenRecord: false,
-
- gpuFreq: false,
- gpuMemTotal: false,
-
- ftrace: false,
- atrace: false,
- ftraceEvents: [],
- ftraceExtraEvents: '',
- atraceCats: [],
- atraceApps: '',
- ftraceBufferSizeKb: 2 * 1024,
- ftraceDrainPeriodMs: 250,
- androidLogs: false,
- androidLogBuffers: [],
- androidFrameTimeline: false,
-
- cpuCoarse: false,
- cpuCoarsePollMs: 1000,
-
- batteryDrain: false,
- batteryDrainPollMs: 1000,
-
- boardSensors: false,
-
- memHiFreq: false,
- meminfo: false,
- meminfoPeriodMs: 1000,
- meminfoCounters: [],
-
- vmstat: false,
- vmstatPeriodMs: 1000,
- vmstatCounters: [],
-
- heapProfiling: false,
- hpSamplingIntervalBytes: 4096,
- hpProcesses: '',
- hpContinuousDumpsPhase: 0,
- hpContinuousDumpsInterval: 0,
- hpSharedMemoryBuffer: 8 * 1048576,
- hpBlockClient: true,
- hpAllHeaps: false,
-
- javaHeapDump: false,
- jpProcesses: '',
- jpContinuousDumpsPhase: 0,
- jpContinuousDumpsInterval: 0,
-
- memLmk: false,
- procStats: false,
- procStatsPeriodMs: 1000,
-
- chromeCategoriesSelected: [],
- };
+ return validateRecordConfig({});
}
export function getDefaultRecordingTargets(): RecordingTarget[] {
@@ -533,7 +539,7 @@
}
export function getBuiltinChromeCategoryList(): string[] {
- // List of static Chrome categories, last updated at Chromium 81.0.4021.0 from
+ // List of static Chrome categories, last updated at 2021-09-09 from HEAD of
// Chromium's //base/trace_event/builtin_categories.h.
return [
'accessibility',
@@ -547,11 +553,12 @@
'blink.animations',
'blink.bindings',
'blink.console',
- 'blink_gc',
'blink.net',
- 'blink_style',
+ 'blink.resource',
'blink.user_timing',
'blink.worker',
+ 'blink_gc',
+ 'blink_style',
'Blob',
'browser',
'browsing_data',
@@ -583,10 +590,10 @@
'drmcursor',
'dwrite',
'DXVA_Decoding',
- 'EarlyJava',
'evdev',
'event',
'exo',
+ 'extensions',
'explore_sites',
'FileSystem',
'file_system_provider',
@@ -644,6 +651,7 @@
'RLZ',
'safe_browsing',
'screenlock_monitor',
+ 'segmentation_platform',
'sequence_manager',
'service_manager',
'ServiceWorker',
@@ -658,7 +666,7 @@
'stadia_rtc',
'startup',
'sync',
- 'sync_lock_contention',
+ 'system_apps',
'test_gpu',
'thread_pool',
'toplevel',
@@ -681,6 +689,7 @@
'disabled-by-default-animation-worklet',
'disabled-by-default-audio',
'disabled-by-default-audio-worklet',
+ 'disabled-by-default-base',
'disabled-by-default-blink.debug',
'disabled-by-default-blink.debug.display_lock',
'disabled-by-default-blink.debug.layout',
@@ -717,7 +726,6 @@
'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',
@@ -744,12 +752,10 @@
'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',
'disabled-by-default-v8.gc',
'disabled-by-default-v8.gc_stats',
'disabled-by-default-v8.ic_stats',
@@ -758,12 +764,11 @@
'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.debug.overlay_planes',
'disabled-by-default-viz.hit_testing_flow',
'disabled-by-default-viz.overdraw',
'disabled-by-default-viz.quads',
@@ -780,7 +785,6 @@
export function createEmptyState(): State {
return {
version: STATE_VERSION,
- route: null,
nextId: 0,
nextNoteId: 1, // 0 is reserved for ephemeral area marking.
nextAreaId: 0,
@@ -798,6 +802,8 @@
metrics: {},
permalink: {},
notes: {},
+ pivotTableConfig: {},
+ pivotTable: {},
recordConfig: createEmptyRecordConfig(),
displayConfigAsPbtxt: false,
@@ -823,15 +829,20 @@
status: {msg: '', timestamp: 0},
currentSelection: null,
- currentHeapProfileFlamegraph: null,
+ currentFlamegraphState: null,
traceConversionInProgress: false,
- video: null,
- videoEnabled: false,
- videoOffset: 0,
- videoNoteIds: [],
- scrubbingEnabled: false,
- flagPauseEnabled: false,
+ perfDebug: false,
+ sidebarVisible: true,
+ hoveredUtid: -1,
+ hoveredPid: -1,
+ hoveredLogsTimestamp: -1,
+ hoveredNoteTimestamp: -1,
+ highlightedSliceId: -1,
+ focusedFlowIdLeft: -1,
+ focusedFlowIdRight: -1,
+ searchIndex: -1,
+
recordingInProgress: false,
recordingCancelled: false,
extensionInstalled: false,
diff --git a/ui/src/common/wasm_engine_proxy.ts b/ui/src/common/wasm_engine_proxy.ts
index 5f7715d..92c7157 100644
--- a/ui/src/common/wasm_engine_proxy.ts
+++ b/ui/src/common/wasm_engine_proxy.ts
@@ -12,8 +12,39 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {assertTrue} from '../base/logging';
+import {assertExists, assertTrue} from '../base/logging';
+
import {Engine, LoadingTracker} from './engine';
+import {EngineWorkerInitMessage} from './worker_messages';
+
+let bundlePath: string;
+let idleWasmWorker: Worker;
+let activeWasmWorker: Worker;
+
+export function initWasm(root: string) {
+ bundlePath = root + 'engine_bundle.js';
+ idleWasmWorker = new Worker(bundlePath);
+}
+
+// This method is called trace_controller whenever a new trace is loaded.
+export function resetEngineWorker(): MessagePort {
+ const channel = new MessageChannel();
+ const port = channel.port1;
+
+ // We keep always an idle worker around, the first one is created by the
+ // main() below, so we can hide the latency of the Wasm initialization.
+ if (activeWasmWorker !== undefined) {
+ activeWasmWorker.terminate();
+ }
+
+ // Swap the active worker with the idle one and create a new idle worker
+ // for the next trace.
+ activeWasmWorker = assertExists(idleWasmWorker);
+ const msg: EngineWorkerInitMessage = {enginePort: port};
+ activeWasmWorker.postMessage(msg, [port]);
+ idleWasmWorker = new Worker(bundlePath);
+ return channel.port2;
+}
/**
* This implementation of Engine uses a WASM backend hosted in a separate
diff --git a/ui/src/common/worker_messages.ts b/ui/src/common/worker_messages.ts
index b60a656..b90f6b2 100644
--- a/ui/src/common/worker_messages.ts
+++ b/ui/src/common/worker_messages.ts
@@ -35,10 +35,6 @@
// the frontend <> controller interaction happens.
controllerPort: MessagePort;
- // For publishing results back to the frontend. This is used for one-way
- // non-retained publish() operations (e.g. track data after a query).
- frontendPort: MessagePort;
-
// For controller <> Chrome extension communication.
extensionPort: MessagePort;
diff --git a/ui/src/controller/adb.ts b/ui/src/controller/adb.ts
index 47783a6..42d8138 100644
--- a/ui/src/controller/adb.ts
+++ b/ui/src/controller/adb.ts
@@ -293,7 +293,7 @@
stream.onClose = () => {};
resolve(stream);
};
- stream.onClose = () => reject();
+ stream.onClose = () => reject(`Failed to openStream svc=${svc}`);
});
}
@@ -350,9 +350,7 @@
};
const key = await crypto.subtle.generateKey(
- keySpec, /*extractable=*/ true, ['sign', 'verify']) as
- CryptoKeyPair;
-
+ keySpec, /*extractable=*/ true, ['sign', 'verify']);
return key;
}
diff --git a/ui/src/controller/adb_socket_controller.ts b/ui/src/controller/adb_socket_controller.ts
index f517f7a..88440b5 100644
--- a/ui/src/controller/adb_socket_controller.ts
+++ b/ui/src/controller/adb_socket_controller.ts
@@ -302,7 +302,7 @@
msgBindService: new perfetto.protos.IPCFrame.BindService(
{serviceName: 'ConsumerPort'})
});
- return new Promise((resolve, _) => {
+ return new Promise<void>((resolve, _) => {
this.resolveBindingPromise = resolve;
this.sendFrame(frame);
});
diff --git a/ui/src/controller/aggregation/aggregation_controller.ts b/ui/src/controller/aggregation/aggregation_controller.ts
index 0892e37..3f4b126 100644
--- a/ui/src/controller/aggregation/aggregation_controller.ts
+++ b/ui/src/controller/aggregation/aggregation_controller.ts
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {Actions} from '../../common/actions';
import {
AggregateData,
Column,
@@ -19,8 +20,12 @@
ThreadStateExtra,
} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
-import {slowlyCountRows} from '../../common/query_iterator';
+import {
+ SLICE_AGGREGATION_PIVOT_TABLE_ID
+} from '../../common/pivot_table_common';
+import {NUM} from '../../common/query_result';
import {Area, Sorting} from '../../common/state';
+import {publishAggregateData} from '../../frontend/publish';
import {Controller} from '../controller';
import {globals} from '../globals';
@@ -29,6 +34,26 @@
kind: string;
}
+function isStringColumn(column: Column): boolean {
+ return column.kind === 'STRING' || column.kind === 'STATE';
+}
+
+function isAreaEqual(area: Area, previousArea?: Area) {
+ if (previousArea === undefined) {
+ return false;
+ }
+ if (previousArea === undefined) {
+ return true;
+ }
+ if (area.startSec !== previousArea.startSec) {
+ return false;
+ }
+ if (area.endSec !== previousArea.endSec) {
+ return false;
+ }
+ return area.tracks.every((element, i) => element === previousArea.tracks[i]);
+}
+
export abstract class AggregationController extends Controller<'main'> {
readonly kind: string;
private previousArea?: Area;
@@ -36,11 +61,9 @@
private requestingData = false;
private queuedRequest = false;
- abstract async createAggregateView(engine: Engine, area: Area):
- Promise<boolean>;
+ abstract createAggregateView(engine: Engine, area: Area): Promise<boolean>;
- abstract async getExtra(engine: Engine, area: Area):
- Promise<ThreadStateExtra|void>;
+ abstract getExtra(engine: Engine, area: Area): Promise<ThreadStateExtra|void>;
abstract getTabName(): string;
abstract getDefaultSorting(): Sorting;
@@ -54,7 +77,9 @@
run() {
const selection = globals.state.currentSelection;
if (selection === null || selection.kind !== 'AREA') {
- globals.publish('AggregateData', {
+ globals.dispatch(Actions.deletePivotTable(
+ {pivotTableId: SLICE_AGGREGATION_PIVOT_TABLE_ID}));
+ publishAggregateData({
data: {
tabName: this.getTabName(),
columns: [],
@@ -69,7 +94,7 @@
const aggregatePreferences =
globals.state.aggregatePreferences[this.args.kind];
- const areaChanged = this.previousArea !== selectedArea;
+ const areaChanged = !isAreaEqual(selectedArea, this.previousArea);
const sortingChanged = aggregatePreferences &&
this.previousSorting !== aggregatePreferences.sorting;
if (!areaChanged && !sortingChanged) return;
@@ -81,9 +106,7 @@
if (sortingChanged) this.previousSorting = aggregatePreferences.sorting;
if (areaChanged) this.previousArea = Object.assign({}, selectedArea);
this.getAggregateData(selectedArea, areaChanged)
- .then(
- data => globals.publish(
- 'AggregateData', {data, kind: this.args.kind}))
+ .then(data => publishAggregateData({data, kind: this.args.kind}))
.finally(() => {
this.requestingData = false;
if (this.queuedRequest) {
@@ -119,7 +142,7 @@
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.numRows();
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);
@@ -137,28 +160,28 @@
return idx;
}
- for (let row = 0; row < numRows; row++) {
- const cols = result.columns;
- for (let col = 0; col < result.columns.length; col++) {
- if (cols[col].stringValues && cols[col].stringValues!.length > 0) {
- 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];
- } else if (
- cols[col].doubleValues && cols[col].doubleValues!.length > 0) {
- data.columns[col].data[row] = cols[col].doubleValues![row];
+ const it = result.iter({});
+ for (let i = 0; it.valid(); it.next(), ++i) {
+ for (const column of data.columns) {
+ const item = it.get(column.columnId);
+ if (item === null) {
+ column.data[i] = isStringColumn(column) ? internString('NULL') : 0;
+ } else if (typeof item === 'string') {
+ column.data[i] = internString(item);
+ } else {
+ column.data[i] = item;
}
}
}
+
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];
+ const result = await this.args.engine.query(
+ `select ifnull(sum(${def.columnId}), 0) as s from ${this.kind}`);
+ let sum = result.firstRow({s: NUM}).s;
if (def.kind === 'TIMESTAMP_NS') {
sum = sum / 1e6;
}
diff --git a/ui/src/controller/aggregation/slice_aggregation_controller.ts b/ui/src/controller/aggregation/slice_aggregation_controller.ts
index f3b2807..8646c45 100644
--- a/ui/src/controller/aggregation/slice_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/slice_aggregation_controller.ts
@@ -12,10 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {Actions} from '../../common/actions';
import {ColumnDef} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
+import {
+ SLICE_AGGREGATION_PIVOT_TABLE_ID
+} from '../../common/pivot_table_common';
import {Area, Sorting} from '../../common/state';
import {toNs} from '../../common/time';
+import {PIVOT_TABLE_FLAG} from '../../frontend/keyboard_event_handler';
import {
ASYNC_SLICE_TRACK_KIND,
Config as AsyncSliceConfig
@@ -28,6 +33,30 @@
import {AggregationController} from './aggregation_controller';
+function addPivotTableOnAreaSelection(
+ selectedTrackIds: number[], startSec: number, endSec: number) {
+ const selectedPivots =
+ [{tableName: 'slice', columnName: 'name', isStackPivot: false}];
+
+ const selectedAggregations = [
+ {tableName: 'slice', columnName: 'dur', aggregation: 'SUM', order: 'DESC'},
+ {tableName: 'slice', columnName: 'dur', aggregation: 'AVG', order: 'DESC'},
+ {tableName: 'slice', columnName: 'id', aggregation: 'COUNT', order: 'DESC'}
+ ];
+
+ globals.dispatch(Actions.addNewPivotTable({
+ name: 'Pivot Table - Slices',
+ pivotTableId: SLICE_AGGREGATION_PIVOT_TABLE_ID,
+ selectedPivots,
+ selectedAggregations,
+ traceTime: {startSec, endSec},
+ selectedTrackIds
+ }));
+
+ globals.dispatch(Actions.setPivotTableRequest(
+ {pivotTableId: SLICE_AGGREGATION_PIVOT_TABLE_ID, action: 'QUERY'}));
+}
+
export class SliceAggregationController extends AggregationController {
async createAggregateView(engine: Engine, area: Area) {
await engine.query(`drop view if exists ${this.kind};`);
@@ -48,8 +77,14 @@
}
}
}
+
if (selectedTrackIds.length === 0) return false;
+ if (PIVOT_TABLE_FLAG.get()) {
+ addPivotTableOnAreaSelection(
+ selectedTrackIds, area.startSec, area.endSec);
+ }
+
const query = `create view ${this.kind} as
SELECT
name,
diff --git a/ui/src/controller/aggregation/thread_aggregation_controller.ts b/ui/src/controller/aggregation/thread_aggregation_controller.ts
index 03eb935..ff7bd6f 100644
--- a/ui/src/controller/aggregation/thread_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/thread_aggregation_controller.ts
@@ -14,7 +14,7 @@
import {ColumnDef, ThreadStateExtra} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
-import {slowlyCountRows} from '../../common/query_iterator';
+import {NUM, NUM_NULL, STR_NULL} from '../../common/query_result';
import {Area, Sorting} from '../../common/state';
import {translateState} from '../../common/thread_state';
import {toNs} from '../../common/time';
@@ -73,31 +73,37 @@
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
+ const query =
+ `select state, io_wait as ioWait, sum(dur) as totalDur 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
+ 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 it = result.iter({
+ state: STR_NULL,
+ ioWait: NUM_NULL,
+ totalDur: NUM,
+ });
const summary: ThreadStateExtra = {
kind: 'THREAD_STATE',
states: [],
- values: new Float64Array(numRows),
+ values: new Float64Array(result.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.totalMs = 0;
+ for (let i = 0; it.valid(); ++i, it.next()) {
+ const state = it.state == null ? undefined : it.state;
+ const ioWait = it.ioWait === null ? undefined : it.ioWait > 0;
summary.states.push(translateState(state, ioWait));
- summary.values[row] = result.columns[2].longValues![row] / 1000000; // ms
+ const ms = it.totalDur / 1000000;
+ summary.values[i] = ms;
+ summary.totalMs += ms;
}
- summary.totalMs = summary.values.reduce((a, b) => a + b, 0);
return summary;
}
diff --git a/ui/src/controller/chrome_proxy_record_controller.ts b/ui/src/controller/chrome_proxy_record_controller.ts
index 4934cc0..5ea3548 100644
--- a/ui/src/controller/chrome_proxy_record_controller.ts
+++ b/ui/src/controller/chrome_proxy_record_controller.ts
@@ -13,15 +13,14 @@
// limitations under the License.
import {binaryDecode, binaryEncode} from '../base/string_utils';
-import {Actions} from '../common/actions';
import {TRACE_SUFFIX} from '../common/constants';
import {
ConsumerPortResponse,
+ hasProperty,
isReadBuffersResponse,
Typed
} from './consumer_port_types';
-import {globals} from './globals';
import {Consumer, RpcConsumerPort} from './record_controller_interfaces';
export interface ChromeExtensionError extends Typed {
@@ -47,8 +46,18 @@
return obj.type === 'ChromeExtensionStatus';
}
-function isGetCategoriesResponse(obj: Typed): obj is GetCategoriesResponse {
- return obj.type === 'GetCategoriesResponse';
+function isObject(obj: unknown): obj is object {
+ return typeof obj === 'object' && obj !== null;
+}
+
+export function isGetCategoriesResponse(obj: unknown):
+ obj is GetCategoriesResponse {
+ if (!(isObject(obj) && hasProperty(obj, 'type') &&
+ obj.type === 'GetCategoriesResponse')) {
+ return false;
+ }
+
+ return hasProperty(obj, 'categories') && Array.isArray(obj.categories);
}
// This class acts as a proxy from the record controller (running in a worker),
@@ -79,10 +88,6 @@
this.sendStatus(message.data.status);
return;
}
- if (isGetCategoriesResponse(message.data)) {
- globals.dispatch(Actions.setChromeCategories(message.data));
- return;
- }
// In this else branch message.data will be a ConsumerPortResponse.
if (isReadBuffersResponse(message.data) && message.data.slices) {
diff --git a/ui/src/controller/consumer_port_types.ts b/ui/src/controller/consumer_port_types.ts
index cb054e1..4e72f5b 100644
--- a/ui/src/controller/consumer_port_types.ts
+++ b/ui/src/controller/consumer_port_types.ts
@@ -18,6 +18,17 @@
type: string;
}
+// A type guard that can be used in order to be able to access the property of
+// an object in a checked manner.
+export function hasProperty<T extends object, P extends string>(
+ obj: T, prop: P): obj is T&{[prop in P]: unknown} {
+ return obj.hasOwnProperty(prop);
+}
+
+export function isTyped(obj: object): obj is Typed {
+ return obj.hasOwnProperty('type');
+}
+
export interface ReadBuffersResponse extends
Typed, perfetto.protos.IReadBuffersResponse {}
export interface EnableTracingResponse extends
diff --git a/ui/src/controller/cpu_profile_controller.ts b/ui/src/controller/cpu_profile_controller.ts
index 05e03e9..932fb64 100644
--- a/ui/src/controller/cpu_profile_controller.ts
+++ b/ui/src/controller/cpu_profile_controller.ts
@@ -13,9 +13,10 @@
// limitations under the License.
import {Engine} from '../common/engine';
-import {slowlyCountRows} from '../common/query_iterator';
+import {NUM, STR} from '../common/query_result';
import {CallsiteInfo, CpuProfileSampleSelection} from '../common/state';
import {CpuProfileDetails} from '../frontend/globals';
+import {publishCpuProfileDetails} from '../frontend/publish';
import {Controller} from './controller';
import {globals} from './globals';
@@ -50,7 +51,7 @@
}
this.requestingData = true;
- globals.publish('CpuProfileDetails', {});
+ publishCpuProfileDetails({});
this.lastSelectedSample = this.copyCpuProfileSample(selection);
this.getSampleData(selectedSample.id)
@@ -65,7 +66,7 @@
stack: sampleData,
};
- globals.publish('CpuProfileDetails', cpuProfileDetails);
+ publishCpuProfileDetails(cpuProfileDetails);
}
})
.finally(() => {
@@ -106,7 +107,7 @@
// 5. Sort the query by the depth of the callstack frames.
const sampleQuery = `
SELECT
- samples.id,
+ samples.id as id,
IFNULL(
(
SELECT name
@@ -115,8 +116,8 @@
LIMIT 1
),
spf.name
- ) AS frame_name,
- spm.name AS mapping_name
+ ) AS name,
+ spm.name AS mapping
FROM cpu_profile_stack_sample AS samples
LEFT JOIN (
SELECT
@@ -143,24 +144,26 @@
const callsites = await this.args.engine.query(sampleQuery);
- if (slowlyCountRows(callsites) < 1) {
+ if (callsites.numRows() === 0) {
return undefined;
}
- const sampleData: CallsiteInfo[] = new Array();
- for (let i = 0; i < slowlyCountRows(callsites); i++) {
- const id = +callsites.columns[0].longValues![i];
- const name = callsites.columns[1].stringValues![i];
- const mapping = callsites.columns[2].stringValues![i];
+ const it = callsites.iter({
+ id: NUM,
+ name: STR,
+ mapping: STR,
+ });
+ const sampleData: CallsiteInfo[] = new Array();
+ for (; it.valid(); it.next()) {
sampleData.push({
- id,
+ id: it.id,
totalSize: 0,
depth: 0,
parentId: 0,
- name,
+ name: it.name,
selfSize: 0,
- mapping,
+ mapping: it.mapping,
merged: false,
highlighted: false
});
diff --git a/ui/src/controller/flamegraph_controller.ts b/ui/src/controller/flamegraph_controller.ts
new file mode 100644
index 0000000..bafad23
--- /dev/null
+++ b/ui/src/controller/flamegraph_controller.ts
@@ -0,0 +1,413 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {
+ ALLOC_SPACE_MEMORY_ALLOCATED_KEY,
+ DEFAULT_VIEWING_OPTION,
+ expandCallsites,
+ findRootSize,
+ mergeCallsites,
+ OBJECTS_ALLOCATED_KEY,
+ OBJECTS_ALLOCATED_NOT_FREED_KEY,
+ PERF_SAMPLES_KEY,
+ SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY
+} from '../common/flamegraph_util';
+import {NUM, STR} from '../common/query_result';
+import {CallsiteInfo, FlamegraphState} from '../common/state';
+import {fromNs} from '../common/time';
+import {FlamegraphDetails} from '../frontend/globals';
+import {publishFlamegraphDetails} from '../frontend/publish';
+
+import {Controller} from './controller';
+import {globals} from './globals';
+
+export interface FlamegraphControllerArgs {
+ engine: Engine;
+}
+const MIN_PIXEL_DISPLAYED = 1;
+
+class TablesCache {
+ private engine: Engine;
+ private cache: Map<string, string>;
+ private prefix: string;
+ private tableId: number;
+ private cacheSizeLimit: number;
+
+ constructor(engine: Engine, prefix: string) {
+ this.engine = engine;
+ this.cache = new Map<string, string>();
+ this.prefix = prefix;
+ this.tableId = 0;
+ this.cacheSizeLimit = 10;
+ }
+
+ async getTableName(query: string): Promise<string> {
+ let tableName = this.cache.get(query);
+ if (tableName === undefined) {
+ // TODO(hjd): This should be LRU.
+ if (this.cache.size > this.cacheSizeLimit) {
+ for (const name of this.cache.values()) {
+ await this.engine.query(`drop table ${name}`);
+ }
+ this.cache.clear();
+ }
+ tableName = `${this.prefix}_${this.tableId++}`;
+ await this.engine.query(
+ `create temp table if not exists ${tableName} as ${query}`);
+ this.cache.set(query, tableName);
+ }
+ return tableName;
+ }
+}
+
+export class FlamegraphController extends Controller<'main'> {
+ private flamegraphDatasets: Map<string, CallsiteInfo[]> = new Map();
+ private lastSelectedFlamegraphState?: FlamegraphState;
+ private requestingData = false;
+ private queuedRequest = false;
+ private flamegraphDetails: FlamegraphDetails = {};
+ private cache: TablesCache;
+
+ constructor(private args: FlamegraphControllerArgs) {
+ super('main');
+ this.cache = new TablesCache(args.engine, 'grouped_callsites');
+ }
+
+ run() {
+ const selection = globals.state.currentFlamegraphState;
+
+ if (!selection) return;
+
+ if (this.shouldRequestData(selection)) {
+ if (this.requestingData) {
+ this.queuedRequest = true;
+ } else {
+ this.requestingData = true;
+ const selectedFlamegraphState: FlamegraphState =
+ this.copyFlamegraphState(selection);
+
+ this.getFlamegraphMetadata(
+ selection.type,
+ selectedFlamegraphState.ts,
+ selectedFlamegraphState.upid)
+ .then(result => {
+ if (result !== undefined) {
+ Object.assign(this.flamegraphDetails, result);
+ }
+
+ // TODO(hjd): Clean this up.
+ if (this.lastSelectedFlamegraphState &&
+ this.lastSelectedFlamegraphState.focusRegex !==
+ selection.focusRegex) {
+ this.flamegraphDatasets.clear();
+ }
+
+ this.lastSelectedFlamegraphState =
+ this.copyFlamegraphState(selection);
+
+ const expandedId = selectedFlamegraphState.expandedCallsite ?
+ selectedFlamegraphState.expandedCallsite.id :
+ -1;
+ const rootSize =
+ selectedFlamegraphState.expandedCallsite === undefined ?
+ undefined :
+ selectedFlamegraphState.expandedCallsite.totalSize;
+
+ const key = `${selectedFlamegraphState.upid};${
+ selectedFlamegraphState.ts}`;
+
+ this.getFlamegraphData(
+ key,
+ selectedFlamegraphState.viewingOption ?
+ selectedFlamegraphState.viewingOption :
+ DEFAULT_VIEWING_OPTION,
+ selection.ts,
+ selectedFlamegraphState.upid,
+ selectedFlamegraphState.type,
+ selectedFlamegraphState.focusRegex)
+ .then(flamegraphData => {
+ if (flamegraphData !== undefined && selection &&
+ selection.kind === selectedFlamegraphState.kind &&
+ selection.id === selectedFlamegraphState.id &&
+ selection.ts === selectedFlamegraphState.ts) {
+ const expandedFlamegraphData =
+ expandCallsites(flamegraphData, expandedId);
+ this.prepareAndMergeCallsites(
+ expandedFlamegraphData,
+ this.lastSelectedFlamegraphState!.viewingOption,
+ rootSize,
+ this.lastSelectedFlamegraphState!.expandedCallsite);
+ }
+ })
+ .finally(() => {
+ this.requestingData = false;
+ if (this.queuedRequest) {
+ this.queuedRequest = false;
+ this.run();
+ }
+ });
+ });
+ }
+ }
+ }
+
+ private copyFlamegraphState(flamegraphState: FlamegraphState):
+ FlamegraphState {
+ return {
+ kind: flamegraphState.kind,
+ id: flamegraphState.id,
+ upid: flamegraphState.upid,
+ ts: flamegraphState.ts,
+ type: flamegraphState.type,
+ expandedCallsite: flamegraphState.expandedCallsite,
+ viewingOption: flamegraphState.viewingOption,
+ focusRegex: flamegraphState.focusRegex,
+ };
+ }
+
+ private shouldRequestData(selection: FlamegraphState) {
+ return selection.kind === 'FLAMEGRAPH_STATE' &&
+ (this.lastSelectedFlamegraphState === undefined ||
+ (this.lastSelectedFlamegraphState !== undefined &&
+ (this.lastSelectedFlamegraphState.id !== selection.id ||
+ this.lastSelectedFlamegraphState.ts !== selection.ts ||
+ this.lastSelectedFlamegraphState.type !== selection.type ||
+ this.lastSelectedFlamegraphState.upid !== selection.upid ||
+ this.lastSelectedFlamegraphState.viewingOption !==
+ selection.viewingOption ||
+ this.lastSelectedFlamegraphState.focusRegex !==
+ selection.focusRegex ||
+ this.lastSelectedFlamegraphState.expandedCallsite !==
+ selection.expandedCallsite)));
+ }
+
+ private prepareAndMergeCallsites(
+ flamegraphData: CallsiteInfo[],
+ viewingOption: string|undefined = DEFAULT_VIEWING_OPTION,
+ rootSize?: number, expandedCallsite?: CallsiteInfo) {
+ const mergedFlamegraphData = mergeCallsites(
+ flamegraphData, this.getMinSizeDisplayed(flamegraphData, rootSize));
+ this.flamegraphDetails.flamegraph = mergedFlamegraphData;
+ this.flamegraphDetails.expandedCallsite = expandedCallsite;
+ this.flamegraphDetails.viewingOption = viewingOption;
+ publishFlamegraphDetails(this.flamegraphDetails);
+ }
+
+
+ async getFlamegraphData(
+ baseKey: string, viewingOption: string, ts: number, upid: number,
+ type: string, focusRegex: string): Promise<CallsiteInfo[]> {
+ let currentData: CallsiteInfo[];
+ const key = `${baseKey}-${viewingOption}`;
+ if (this.flamegraphDatasets.has(key)) {
+ currentData = this.flamegraphDatasets.get(key)!;
+ } else {
+ // TODO(hjd): Show loading state.
+
+ // Collecting data for drawing flamegraph for selected 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);
+ this.flamegraphDatasets.set(key, currentData);
+ }
+ return currentData;
+ }
+
+ async getFlamegraphDataFromTables(
+ tableName: string, viewingOption = DEFAULT_VIEWING_OPTION,
+ focusRegex: string) {
+ let orderBy = '';
+ let totalColumnName: 'cumulativeSize'|'cumulativeAllocSize'|
+ 'cumulativeCount'|'cumulativeAllocCount' = 'cumulativeSize';
+ let selfColumnName: 'size'|'count' = 'size';
+ // TODO(fmayer): Improve performance so this is no longer necessary.
+ // Alternatively consider collapsing frames of the same label.
+ const maxDepth = 100;
+ switch (viewingOption) {
+ case ALLOC_SPACE_MEMORY_ALLOCATED_KEY:
+ orderBy = `where cumulative_alloc_size > 0 and depth < ${
+ maxDepth} order by depth, parent_id,
+ cumulative_alloc_size desc, name`;
+ totalColumnName = 'cumulativeAllocSize';
+ selfColumnName = 'size';
+ break;
+ case OBJECTS_ALLOCATED_NOT_FREED_KEY:
+ orderBy = `where cumulative_count > 0 and depth < ${
+ maxDepth} order by depth, parent_id,
+ cumulative_count desc, name`;
+ totalColumnName = 'cumulativeCount';
+ selfColumnName = 'count';
+ break;
+ case OBJECTS_ALLOCATED_KEY:
+ orderBy = `where cumulative_alloc_count > 0 and depth < ${
+ maxDepth} order by depth, parent_id,
+ cumulative_alloc_count desc, name`;
+ totalColumnName = 'cumulativeAllocCount';
+ selfColumnName = 'count';
+ break;
+ case PERF_SAMPLES_KEY:
+ case SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY:
+ orderBy = `where cumulative_size > 0 and depth < ${
+ maxDepth} order by depth, parent_id,
+ cumulative_size desc, name`;
+ totalColumnName = 'cumulativeSize';
+ selfColumnName = 'size';
+ break;
+ default:
+ break;
+ }
+
+ const callsites = await this.args.engine.query(`
+ SELECT
+ id as hash,
+ IFNULL(IFNULL(DEMANGLE(name), name), '[NULL]') as name,
+ IFNULL(parent_id, -1) as parentHash,
+ depth,
+ cumulative_size as cumulativeSize,
+ cumulative_alloc_size as cumulativeAllocSize,
+ cumulative_count as cumulativeCount,
+ cumulative_alloc_count as cumulativeAllocCount,
+ map_name as mapping,
+ size,
+ count,
+ IFNULL(source_file, '') as sourceFile,
+ IFNULL(line_number, -1) as lineNumber
+ from ${tableName} ${orderBy}`);
+
+ const flamegraphData: CallsiteInfo[] = [];
+ const hashToindex: Map<number, number> = new Map();
+ const it = callsites.iter({
+ hash: NUM,
+ name: STR,
+ parentHash: NUM,
+ depth: NUM,
+ cumulativeSize: NUM,
+ cumulativeAllocSize: NUM,
+ cumulativeCount: NUM,
+ cumulativeAllocCount: NUM,
+ mapping: STR,
+ sourceFile: STR,
+ lineNumber: NUM,
+ size: NUM,
+ count: NUM,
+ });
+ for (let i = 0; it.valid(); ++i, it.next()) {
+ const hash = it.hash;
+ let name = it.name;
+ const parentHash = it.parentHash;
+ const depth = it.depth;
+ const totalSize = it[totalColumnName];
+ const selfSize = it[selfColumnName];
+ const mapping = it.mapping;
+ const highlighted = focusRegex !== '' &&
+ name.toLocaleLowerCase().includes(focusRegex.toLocaleLowerCase());
+ const parentId =
+ hashToindex.has(+parentHash) ? hashToindex.get(+parentHash)! : -1;
+
+ let location: string|undefined;
+ if (/[a-zA-Z]/i.test(it.sourceFile)) {
+ location = it.sourceFile;
+ if (it.lineNumber !== -1) {
+ location += `:${it.lineNumber}`;
+ }
+ }
+
+ if (depth === maxDepth - 1) {
+ name += ' [tree truncated]';
+ }
+ // Instead of hash, we will store index of callsite in this original array
+ // as an id of callsite. That way, we have quicker access to parent and it
+ // will stay unique:
+ hashToindex.set(hash, i);
+
+ flamegraphData.push({
+ id: i,
+ totalSize,
+ depth,
+ parentId,
+ name,
+ selfSize,
+ mapping,
+ merged: false,
+ highlighted,
+ location
+ });
+ }
+ return flamegraphData;
+ }
+
+ private async prepareViewsAndTables(
+ ts: number, upid: number, type: string,
+ focusRegex: string): Promise<string> {
+ // Creating unique names for views so we can reuse and not delete them
+ // for each marker.
+ let focusRegexConditional = '';
+ if (focusRegex !== '') {
+ const linkingWord = type === 'perf' ? 'and' : 'where';
+ focusRegexConditional = `${linkingWord} focus_str = '${focusRegex}'`;
+ }
+
+ /*
+ * TODO(octaviant) this branching should be eliminated for simplicity.
+ */
+ if (type === 'perf') {
+ return this.cache.getTableName(
+ `select id, name, map_name, parent_id, depth, cumulative_size,
+ cumulative_alloc_size, cumulative_count, cumulative_alloc_count,
+ size, alloc_size, count, alloc_count, source_file, line_number
+ from experimental_flamegraph
+ where profile_type = "${type}" and ts <= ${ts} and upid = ${upid}
+ ${focusRegexConditional}`);
+ }
+ return this.cache.getTableName(
+ `select id, name, map_name, parent_id, depth, cumulative_size,
+ cumulative_alloc_size, cumulative_count, cumulative_alloc_count,
+ size, alloc_size, count, alloc_count, source_file, line_number
+ from experimental_flamegraph(${ts}, ${upid}, '${type}') ${
+ focusRegexConditional}`);
+ }
+
+ 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);
+ if (rootSize === undefined) {
+ rootSize = findRootSize(flamegraphData);
+ }
+ return MIN_PIXEL_DISPLAYED * rootSize / width;
+ }
+
+ async getFlamegraphMetadata(type: string, ts: number, upid: number) {
+ // Don't do anything if selection of the marker stayed the same.
+ if ((this.lastSelectedFlamegraphState !== undefined &&
+ ((this.lastSelectedFlamegraphState.ts === ts &&
+ this.lastSelectedFlamegraphState.upid === upid)))) {
+ return undefined;
+ }
+
+ // Collecting data for more information about profile, such as:
+ // total memory allocated, memory that is allocated and not freed.
+ const result = await this.args.engine.query(
+ `select pid from process where upid = ${upid}`);
+ const pid = result.firstRow({pid: NUM}).pid;
+ const startTime = fromNs(ts) - globals.state.traceTime.startSec;
+ return {ts: startTime, tsNs: ts, pid, upid, type};
+ }
+}
diff --git a/ui/src/controller/flow_events_controller.ts b/ui/src/controller/flow_events_controller.ts
index 87dd298..a5a80cd 100644
--- a/ui/src/controller/flow_events_controller.ts
+++ b/ui/src/controller/flow_events_controller.ts
@@ -13,10 +13,11 @@
// limitations under the License.
import {Engine} from '../common/engine';
-import {slowlyCountRows} from '../common/query_iterator';
+import {NUM, STR_NULL} from '../common/query_result';
import {Area} from '../common/state';
import {fromNs, toNs} from '../common/time';
import {Flow} from '../frontend/globals';
+import {publishConnectedFlows, publishSelectedFlows} from '../frontend/publish';
import {
ACTUAL_FRAMES_SLICE_TRACK_KIND,
Config as ActualConfig
@@ -43,34 +44,53 @@
}
queryFlowEvents(query: string, callback: (flows: Flow[]) => void) {
- this.args.engine.query(query).then(res => {
+ this.args.engine.query(query).then(result => {
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 it = result.iter({
+ beginSliceId: NUM,
+ beginTrackId: NUM,
+ beginSliceName: STR_NULL,
+ beginSliceCategory: STR_NULL,
+ beginSliceStartTs: NUM,
+ beginSliceEndTs: NUM,
+ beginDepth: NUM,
+ endSliceId: NUM,
+ endTrackId: NUM,
+ endSliceName: STR_NULL,
+ endSliceCategory: STR_NULL,
+ endSliceStartTs: NUM,
+ endSliceEndTs: NUM,
+ endDepth: NUM,
+ name: STR_NULL,
+ category: STR_NULL,
+ id: NUM,
+ });
+ for (; it.valid(); it.next()) {
+ const beginSliceId = it.beginSliceId;
+ const beginTrackId = it.beginTrackId;
+ const beginSliceName =
+ it.beginSliceName === null ? 'NULL' : it.beginSliceName;
+ const beginSliceCategory =
+ it.beginSliceCategory === null ? 'NULL' : it.beginSliceCategory;
+ const beginSliceStartTs = fromNs(it.beginSliceStartTs);
+ const beginSliceEndTs = fromNs(it.beginSliceEndTs);
+ const beginDepth = it.beginDepth;
- 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];
+ const endSliceId = it.endSliceId;
+ const endTrackId = it.endTrackId;
+ const endSliceName =
+ it.endSliceName === null ? 'NULL' : it.endSliceName;
+ const endSliceCategory =
+ it.endSliceCategory === null ? 'NULL' : it.endSliceCategory;
+ const endSliceStartTs = fromNs(it.endSliceStartTs);
+ const endSliceEndTs = fromNs(it.endSliceEndTs);
+ const endDepth = it.endDepth;
// 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];
+ const category = it.category === null ? undefined : it.category;
+ const name = it.name === null ? undefined : it.name;
+ const id = it.id;
flows.push({
id,
@@ -110,19 +130,29 @@
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
+ f.slice_out as beginSliceId,
+ t1.track_id as beginTrackId,
+ t1.name as beginSliceName,
+ t1.category as beginSliceCategory,
+ t1.ts as beginSliceStartTs,
+ (t1.ts+t1.dur) as beginSliceEndTs,
+ t1.depth as beginDepth,
+ f.slice_in as endSliceId,
+ t2.track_id as endTrackId,
+ t2.name as endSliceName,
+ t2.category as endSliceCategory,
+ t2.ts as endSliceStartTs,
+ (t2.ts+t2.dur) as endSliceEndTs,
+ t2.depth as endDepth,
+ extract_arg(f.arg_set_id, 'cat') as category,
+ extract_arg(f.arg_set_id, 'name') as name,
+ f.id as 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));
+ query, (flows: Flow[]) => publishConnectedFlows(flows));
}
areaSelected(areaId: string) {
@@ -161,13 +191,23 @@
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
+ f.slice_out as beginSliceId,
+ t1.track_id as beginTrackId,
+ t1.name as beginSliceName,
+ t1.category as beginSliceCategory,
+ t1.ts as beginSliceStartTs,
+ (t1.ts+t1.dur) as beginSliceEndTs,
+ t1.depth as beginDepth,
+ f.slice_in as endSliceId,
+ t2.track_id as endTrackId,
+ t2.name as endSliceName,
+ t2.category as endSliceCategory,
+ t2.ts as endSliceStartTs,
+ (t2.ts+t2.dur) as endSliceEndTs,
+ t2.depth as endDepth,
+ extract_arg(f.arg_set_id, 'cat') as category,
+ extract_arg(f.arg_set_id, 'name') as name,
+ f.id as id
from flow f
join slice t1 on f.slice_out = t1.slice_id
join slice t2 on f.slice_in = t2.slice_id
@@ -178,29 +218,31 @@
(t2.track_id in ${tracks}
and (t2.ts <= ${endNs} and t2.ts >= ${startNs}))
`;
- this.queryFlowEvents(
- query, (flows: Flow[]) => globals.publish('SelectedFlows', flows));
+ this.queryFlowEvents(query, (flows: Flow[]) => publishSelectedFlows(flows));
}
refreshVisibleFlows() {
const selection = globals.state.currentSelection;
if (!selection) {
this.lastSelectedKind = 'NONE';
- globals.publish('ConnectedFlows', []);
- globals.publish('SelectedFlows', []);
+ publishConnectedFlows([]);
+ publishSelectedFlows([]);
return;
}
- if (selection && selection.kind === 'CHROME_SLICE') {
+ // TODO(b/155483804): This is a hack as annotation slices don't contain
+ // flows. We should tidy this up when fixing this bug.
+ if (selection && selection.kind === 'CHROME_SLICE' &&
+ selection.table !== 'annotation') {
this.sliceSelected(selection.id);
} else {
- globals.publish('ConnectedFlows', []);
+ publishConnectedFlows([]);
}
if (selection && selection.kind === 'AREA') {
this.areaSelected(selection.areaId);
} else {
- globals.publish('SelectedFlows', []);
+ publishSelectedFlows([]);
}
}
diff --git a/ui/src/controller/globals.ts b/ui/src/controller/globals.ts
index d47af46..f479f37 100644
--- a/ui/src/controller/globals.ts
+++ b/ui/src/controller/globals.ts
@@ -12,26 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {Patch, produce} from 'immer';
+import {applyPatches, Patch} from 'immer';
import {assertExists} from '../base/logging';
-import {Remote} from '../base/remote';
-import {DeferredAction, StateActions} from '../common/actions';
+import {DeferredAction} from '../common/actions';
import {createEmptyState, State} from '../common/state';
+import {globals as frontendGlobals} from '../frontend/globals';
import {ControllerAny} from './controller';
-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'|'HasFtrace'|
- 'ConversionJobStatusUpdate';
-
export interface App {
state: State;
dispatch(action: DeferredAction): void;
- publish(what: PublishKinds, data: {}, transferList?: Array<{}>): void;
}
/**
@@ -40,28 +31,30 @@
class Globals implements App {
private _state?: State;
private _rootController?: ControllerAny;
- private _frontend?: Remote;
private _runningControllers = false;
- private _queuedActions = new Array<DeferredAction>();
- initialize(rootController: ControllerAny, frontendProxy: Remote) {
+ initialize(rootController: ControllerAny) {
this._rootController = rootController;
- this._frontend = frontendProxy;
this._state = createEmptyState();
}
dispatch(action: DeferredAction): void {
- this.dispatchMultiple([action]);
+ frontendGlobals.dispatch(action);
}
+ // Send the passed dispatch actions to the frontend. The frontend logic
+ // will run the actions, compute the new state and invoke patchState() so
+ // our copy is updated.
dispatchMultiple(actions: DeferredAction[]): void {
- this._queuedActions = this._queuedActions.concat(actions);
+ for (const action of actions) {
+ this.dispatch(action);
+ }
+ }
- // If we are in the middle of running the controllers, queue the actions
- // and run them at the end of the run, so the state is atomically updated
- // only at the end and all controllers see the same state.
- if (this._runningControllers) return;
-
+ // This is called by the frontend logic which now owns and handle the
+ // source-of-truth state, to give us an update on the newer state updates.
+ patchState(patches: Patch[]): void {
+ this._state = applyPatches(assertExists(this._state), patches);
this.runControllers();
}
@@ -69,21 +62,9 @@
if (this._runningControllers) throw new Error('Re-entrant call detected');
// Run controllers locally until all state machines reach quiescence.
- let runAgain = false;
- const patches: Patch[] = [];
- for (let iter = 0; runAgain || this._queuedActions.length > 0; iter++) {
+ let runAgain = true;
+ for (let iter = 0; runAgain; iter++) {
if (iter > 100) throw new Error('Controllers are stuck in a livelock');
- const actions = this._queuedActions;
- this._queuedActions = new Array<DeferredAction>();
-
- for (const action of actions) {
- const originalLength = patches.length;
- const morePatches = this.applyAction(action);
- patches.length += morePatches.length;
- for (let i = 0; i < morePatches.length; ++i) {
- patches[i + originalLength] = morePatches[i];
- }
- }
this._runningControllers = true;
try {
runAgain = assertExists(this._rootController).invoke();
@@ -91,55 +72,12 @@
this._runningControllers = false;
}
}
- assertExists(this._frontend).send<void>('patchState', [patches]);
- }
-
- // TODO: this needs to be cleaned up.
- publish(what: PublishKinds, data: {}, transferList?: Transferable[]) {
- assertExists(this._frontend)
- .send<void>(`publish${what}`, [data], transferList);
- }
-
- // Returns the port of the MessageChannel that can be used to communicate with
- // the Wasm Engine (issue SQL queries and retrieve results).
- resetEngineWorker() {
- const chan = new MessageChannel();
- const port = chan.port1;
- // Invokes resetEngineWorker() in frontend/index.ts. It will spawn a new
- // worker and assign it the passed |port|.
- assertExists(this._frontend).send<void>('resetEngineWorker', [port], [
- port
- ]);
- return chan.port2;
}
get state(): State {
return assertExists(this._state);
}
- applyAction(action: DeferredAction): Patch[] {
- assertExists(this._state);
- const patches: Patch[] = [];
-
- // 'produce' creates a immer proxy which wraps the current state turning
- // all imperative mutations of the state done in the callback into
- // immutable changes to the returned state.
- this._state = produce(
- this.state,
- draft => {
- // tslint:disable-next-line no-any
- (StateActions as any)[action.type](draft, action.args);
- },
- (morePatches, _) => {
- const originalLength = patches.length;
- patches.length += morePatches.length;
- for (let i = 0; i < morePatches.length; ++i) {
- patches[i + originalLength] = morePatches[i];
- }
- });
- return patches;
- }
-
resetForTesting() {
this._state = undefined;
this._rootController = undefined;
diff --git a/ui/src/controller/heap_profile_controller.ts b/ui/src/controller/heap_profile_controller.ts
deleted file mode 100644
index 37af362..0000000
--- a/ui/src/controller/heap_profile_controller.ts
+++ /dev/null
@@ -1,370 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {
- ALLOC_SPACE_MEMORY_ALLOCATED_KEY,
- DEFAULT_VIEWING_OPTION,
- expandCallsites,
- findRootSize,
- mergeCallsites,
- OBJECTS_ALLOCATED_KEY,
- 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';
-
-import {Controller} from './controller';
-import {globals} from './globals';
-
-export interface HeapProfileControllerArgs {
- engine: Engine;
-}
-const MIN_PIXEL_DISPLAYED = 1;
-
-class TablesCache {
- private engine: Engine;
- private cache: Map<string, string>;
- private prefix: string;
- private tableId: number;
- private cacheSizeLimit: number;
-
- constructor(engine: Engine, prefix: string) {
- this.engine = engine;
- this.cache = new Map<string, string>();
- this.prefix = prefix;
- this.tableId = 0;
- this.cacheSizeLimit = 10;
- }
-
- async getTableName(query: string): Promise<string> {
- let tableName = this.cache.get(query);
- if (tableName === undefined) {
- // TODO(hjd): This should be LRU.
- if (this.cache.size > this.cacheSizeLimit) {
- for (const name of this.cache.values()) {
- await this.engine.query(`drop table ${name}`);
- }
- this.cache.clear();
- }
- tableName = `${this.prefix}_${this.tableId++}`;
- await this.engine.query(
- `create temp table if not exists ${tableName} as ${query}`);
- this.cache.set(query, tableName);
- }
- return tableName;
- }
-}
-
-export class HeapProfileController extends Controller<'main'> {
- private flamegraphDatasets: Map<string, CallsiteInfo[]> = new Map();
- private lastSelectedHeapProfile?: HeapProfileFlamegraph;
- private requestingData = false;
- private queuedRequest = false;
- private heapProfileDetails: HeapProfileDetails = {};
- private cache: TablesCache;
-
- constructor(private args: HeapProfileControllerArgs) {
- super('main');
- this.cache = new TablesCache(args.engine, 'grouped_callsites');
- }
-
- run() {
- const selection = globals.state.currentHeapProfileFlamegraph;
-
- if (!selection) return;
-
- if (this.shouldRequestData(selection)) {
- if (this.requestingData) {
- this.queuedRequest = true;
- } else {
- this.requestingData = true;
- const selectedHeapProfile: HeapProfileFlamegraph =
- this.copyHeapProfile(selection);
-
- this.getHeapProfileMetadata(
- selection.type,
- selectedHeapProfile.ts,
- selectedHeapProfile.upid)
- .then(result => {
- if (result !== undefined) {
- Object.assign(this.heapProfileDetails, result);
- }
-
- // TODO(hjd): Clean this up.
- if (this.lastSelectedHeapProfile &&
- this.lastSelectedHeapProfile.focusRegex !==
- selection.focusRegex) {
- this.flamegraphDatasets.clear();
- }
-
- this.lastSelectedHeapProfile = this.copyHeapProfile(selection);
-
- const expandedId = selectedHeapProfile.expandedCallsite ?
- selectedHeapProfile.expandedCallsite.id :
- -1;
- const rootSize =
- selectedHeapProfile.expandedCallsite === undefined ?
- undefined :
- selectedHeapProfile.expandedCallsite.totalSize;
-
- const key =
- `${selectedHeapProfile.upid};${selectedHeapProfile.ts}`;
-
- this.getFlamegraphData(
- key,
- selectedHeapProfile.viewingOption ?
- selectedHeapProfile.viewingOption :
- DEFAULT_VIEWING_OPTION,
- selection.ts,
- selectedHeapProfile.upid,
- selectedHeapProfile.type,
- selectedHeapProfile.focusRegex)
- .then(flamegraphData => {
- if (flamegraphData !== undefined && selection &&
- selection.kind === selectedHeapProfile.kind &&
- selection.id === selectedHeapProfile.id &&
- selection.ts === selectedHeapProfile.ts) {
- const expandedFlamegraphData =
- expandCallsites(flamegraphData, expandedId);
- this.prepareAndMergeCallsites(
- expandedFlamegraphData,
- this.lastSelectedHeapProfile!.viewingOption,
- rootSize,
- this.lastSelectedHeapProfile!.expandedCallsite);
- }
- })
- .finally(() => {
- this.requestingData = false;
- if (this.queuedRequest) {
- this.queuedRequest = false;
- this.run();
- }
- });
- });
- }
- }
- }
-
- private copyHeapProfile(heapProfile: HeapProfileFlamegraph):
- HeapProfileFlamegraph {
- return {
- kind: heapProfile.kind,
- id: heapProfile.id,
- upid: heapProfile.upid,
- ts: heapProfile.ts,
- type: heapProfile.type,
- expandedCallsite: heapProfile.expandedCallsite,
- viewingOption: heapProfile.viewingOption,
- focusRegex: heapProfile.focusRegex,
- };
- }
-
- private shouldRequestData(selection: HeapProfileFlamegraph) {
- return selection.kind === 'HEAP_PROFILE_FLAMEGRAPH' &&
- (this.lastSelectedHeapProfile === undefined ||
- (this.lastSelectedHeapProfile !== undefined &&
- (this.lastSelectedHeapProfile.id !== selection.id ||
- this.lastSelectedHeapProfile.ts !== selection.ts ||
- this.lastSelectedHeapProfile.type !== selection.type ||
- this.lastSelectedHeapProfile.upid !== selection.upid ||
- this.lastSelectedHeapProfile.viewingOption !==
- selection.viewingOption ||
- this.lastSelectedHeapProfile.focusRegex !== selection.focusRegex ||
- this.lastSelectedHeapProfile.expandedCallsite !==
- selection.expandedCallsite)));
- }
-
- private prepareAndMergeCallsites(
- flamegraphData: CallsiteInfo[],
- viewingOption: string|undefined = DEFAULT_VIEWING_OPTION,
- rootSize?: number, expandedCallsite?: CallsiteInfo) {
- const mergedFlamegraphData = mergeCallsites(
- flamegraphData, this.getMinSizeDisplayed(flamegraphData, rootSize));
- this.heapProfileDetails.flamegraph = mergedFlamegraphData;
- this.heapProfileDetails.expandedCallsite = expandedCallsite;
- this.heapProfileDetails.viewingOption = viewingOption;
- globals.publish('HeapProfileDetails', this.heapProfileDetails);
- }
-
-
- async getFlamegraphData(
- baseKey: string, viewingOption: string, ts: number, upid: number,
- type: string, focusRegex: string): Promise<CallsiteInfo[]> {
- let currentData: CallsiteInfo[];
- const key = `${baseKey}-${viewingOption}`;
- if (this.flamegraphDatasets.has(key)) {
- currentData = this.flamegraphDatasets.get(key)!;
- } else {
- // TODO(hjd): 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);
- this.flamegraphDatasets.set(key, currentData);
- }
- return currentData;
- }
-
- async getFlamegraphDataFromTables(
- tableName: string, viewingOption = DEFAULT_VIEWING_OPTION,
- focusRegex: string) {
- let orderBy = '';
- let sizeIndex = 4;
- let selfIndex = 9;
- // TODO(fmayer): Improve performance so this is no longer necessary.
- // Alternatively consider collapsing frames of the same label.
- const maxDepth = 100;
- switch (viewingOption) {
- case SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY:
- orderBy = `where cumulative_size > 0 and depth < ${
- maxDepth} order by depth, parent_id,
- cumulative_size desc, name`;
- sizeIndex = 4;
- selfIndex = 9;
- break;
- case ALLOC_SPACE_MEMORY_ALLOCATED_KEY:
- orderBy = `where cumulative_alloc_size > 0 and depth < ${
- maxDepth} order by depth, parent_id,
- cumulative_alloc_size desc, name`;
- sizeIndex = 5;
- selfIndex = 9;
- break;
- case OBJECTS_ALLOCATED_NOT_FREED_KEY:
- orderBy = `where cumulative_count > 0 and depth < ${
- maxDepth} order by depth, parent_id,
- cumulative_count desc, name`;
- sizeIndex = 6;
- selfIndex = 10;
- break;
- case OBJECTS_ALLOCATED_KEY:
- orderBy = `where cumulative_alloc_count > 0 and depth < ${
- maxDepth} order by depth, parent_id,
- cumulative_alloc_count desc, name`;
- sizeIndex = 7;
- selfIndex = 10;
- break;
- default:
- break;
- }
-
- const callsites = await this.args.engine.query(
- `SELECT id, IFNULL(DEMANGLE(name), name), IFNULL(parent_id, -1), depth,
- cumulative_size, cumulative_alloc_size, cumulative_count,
- cumulative_alloc_count, map_name, size, count,
- IFNULL(source_file, ''), IFNULL(line_number, -1)
- from ${tableName} ${orderBy}`);
-
- const flamegraphData: CallsiteInfo[] = new Array();
- const hashToindex: Map<number, number> = new Map();
- for (let i = 0; i < slowlyCountRows(callsites); i++) {
- const hash = callsites.columns[0].longValues![i];
- let name = callsites.columns[1].stringValues![i];
- const parentHash = callsites.columns[2].longValues![i];
- const depth = +callsites.columns[3].longValues![i];
- 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;
-
- let location: string|undefined;
- if (callsites.columns[11].stringValues != null &&
- /[a-zA-Z]/i.test(callsites.columns[11].stringValues[i])) {
- location = callsites.columns[11].stringValues[i];
- if (callsites.columns[12].longValues != null &&
- callsites.columns[12].longValues[i] !== -1) {
- location += `:${callsites.columns[12].longValues[i].toString()}`;
- }
- }
-
- if (depth === maxDepth - 1) {
- name += ' [tree truncated]';
- }
- hashToindex.set(+hash, i);
- // Instead of hash, we will store index of callsite in this original array
- // as an id of callsite. That way, we have quicker access to parent and it
- // will stay unique.
- flamegraphData.push({
- id: i,
- totalSize,
- depth,
- parentId,
- name,
- selfSize,
- mapping,
- merged: false,
- highlighted,
- location
- });
- }
- return flamegraphData;
- }
-
- private async prepareViewsAndTables(
- ts: number, upid: number, type: string,
- focusRegex: string): Promise<string> {
- // Creating unique names for views so we can reuse and not delete them
- // for each marker.
- let whereClause = '';
- if (focusRegex !== '') {
- whereClause = `where focus_str = '${focusRegex}'`;
- }
-
- return this.cache.getTableName(
- `select id, name, map_name, parent_id, depth, cumulative_size,
- cumulative_alloc_size, cumulative_count, cumulative_alloc_count,
- size, alloc_size, count, alloc_count, source_file, line_number
- from experimental_flamegraph(${ts}, ${upid}, '${type}') ${
- whereClause}`);
- }
-
- 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);
- if (rootSize === undefined) {
- rootSize = findRootSize(flamegraphData);
- }
- return MIN_PIXEL_DISPLAYED * rootSize / width;
- }
-
- async getHeapProfileMetadata(type: string, ts: number, upid: number) {
- // Don't do anything if selection of the marker stayed the same.
- if ((this.lastSelectedHeapProfile !== undefined &&
- ((this.lastSelectedHeapProfile.ts === ts &&
- this.lastSelectedHeapProfile.upid === upid)))) {
- return undefined;
- }
-
- // Collecting data for more information about heap profile, such as:
- // total memory allocated, memory that is allocated and not freed.
- const pidValue = await this.args.engine.query(
- `select pid from process where upid = ${upid}`);
- const pid = pidValue.columns[0].longValues![0];
- const startTime = fromNs(ts) - globals.state.traceTime.startSec;
- return {ts: startTime, tsNs: ts, pid, upid, type};
- }
-}
diff --git a/ui/src/controller/index.ts b/ui/src/controller/index.ts
index 9f5add7..5b4bbdd 100644
--- a/ui/src/controller/index.ts
+++ b/ui/src/controller/index.ts
@@ -12,38 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import '../tracks/all_controller';
+import '../gen/all_tracks';
-import {reportError, setErrorHandler} from '../base/logging';
-import {Remote} from '../base/remote';
+import {assertTrue} from '../base/logging';
import {ControllerWorkerInitMessage} from '../common/worker_messages';
import {AppController} from './app_controller';
import {globals} from './globals';
-function main() {
- self.addEventListener('error', e => reportError(e));
- self.addEventListener('unhandledrejection', e => reportError(e));
- let initialized = false;
- self.onmessage = (e: MessageEvent) => {
- if (initialized) {
- console.error('Already initialized');
- return;
- }
- initialized = true;
- const data = e.data as ControllerWorkerInitMessage;
- const frontendPort = data.frontendPort;
- const controllerPort = data.controllerPort;
- const extensionPort = data.extensionPort;
- const errorReportingPort = data.errorReportingPort;
- setErrorHandler((err: string) => errorReportingPort.postMessage(err));
- const frontend = new Remote(frontendPort);
- controllerPort.onmessage = ({data}) => globals.dispatch(data);
-
- globals.initialize(new AppController(extensionPort), frontend);
- };
+let initialized = false;
+export function initController(init: ControllerWorkerInitMessage) {
+ assertTrue(!initialized);
+ initialized = true;
+ const controllerPort = init.controllerPort;
+ const extensionPort = init.extensionPort;
+ controllerPort.onmessage = ({data}) => globals.patchState(data);
+ globals.initialize(new AppController(extensionPort));
}
-main();
// For devtools-based debugging.
-(self as {} as {globals: {}}).globals = globals;
+(self as {} as {controllerGlobals: {}}).controllerGlobals = globals;
diff --git a/ui/src/controller/loading_manager.ts b/ui/src/controller/loading_manager.ts
index 3814933..5b0e0cf 100644
--- a/ui/src/controller/loading_manager.ts
+++ b/ui/src/controller/loading_manager.ts
@@ -13,7 +13,7 @@
// limitations under the License.
import {LoadingTracker} from '../common/engine';
-import {globals} from './globals';
+import {publishLoading} from '../frontend/publish';
// Used to keep track of whether the engine is currently querying.
export class LoadingManager implements LoadingTracker {
@@ -38,7 +38,7 @@
if (this.numQueuedQueries === 0 ||
Math.abs(this.numLastUpdate - this.numQueuedQueries) > 2) {
this.numLastUpdate = this.numQueuedQueries;
- globals.publish('Loading', this.numQueuedQueries);
+ publishLoading(this.numQueuedQueries);
}
}
}
diff --git a/ui/src/controller/logs_controller.ts b/ui/src/controller/logs_controller.ts
index 7d1d49f..50deb2b 100644
--- a/ui/src/controller/logs_controller.ts
+++ b/ui/src/controller/logs_controller.ts
@@ -20,8 +20,9 @@
LogEntriesKey,
LogExistsKey
} from '../common/logs';
-import {slowlyCountRows} from '../common/query_iterator';
+import {NUM, STR} from '../common/query_result';
import {fromNs, TimeSpan, toNsCeil, toNsFloor} from '../common/time';
+import {publishTrackData} from '../frontend/publish';
import {Controller} from './controller';
import {App} from './globals';
@@ -31,21 +32,28 @@
const vizStartNs = toNsFloor(span.start);
const vizEndNs = toNsCeil(span.end);
- const countResult = await engine.queryOneRow(`
- select min(ts), max(ts), count(ts)
+ const countResult = await engine.query(`
+ select
+ ifnull(min(ts), 0) as minTs,
+ ifnull(max(ts), 0) as maxTs,
+ count(ts) as countTs
from android_logs where ts >= ${vizStartNs} and ts <= ${vizEndNs}`);
- const firstRowNs = countResult[0];
- const lastRowNs = countResult[1];
- const total = countResult[2];
+ const countRow = countResult.firstRow({minTs: NUM, maxTs: NUM, countTs: NUM});
- const minResult = await engine.queryOneRow(`
- select max(ts) from android_logs where ts < ${vizStartNs}`);
- const startNs = minResult[0];
+ const firstRowNs = countRow.minTs;
+ const lastRowNs = countRow.maxTs;
+ const total = countRow.countTs;
- const maxResult = await engine.queryOneRow(`
- select min(ts) from android_logs where ts > ${vizEndNs}`);
- const endNs = maxResult[0];
+ const minResult = await engine.query(`
+ select ifnull(max(ts), 0) as maxTs from android_logs where ts < ${
+ vizStartNs}`);
+ const startNs = minResult.firstRow({maxTs: NUM}).maxTs;
+
+ const maxResult = await engine.query(`
+ select ifnull(min(ts), 0) as minTs from android_logs where ts > ${
+ vizEndNs}`);
+ const endNs = maxResult.firstRow({minTs: NUM}).minTs;
const trace = await engine.getTraceTimeBounds();
const startTs = startNs ? fromNs(startNs) : trace.start;
@@ -68,27 +76,31 @@
const vizEndNs = toNsCeil(span.end);
const vizSqlBounds = `ts >= ${vizStartNs} and ts <= ${vizEndNs}`;
- const rowsResult =
- await engine.query(`select ts, prio, tag, msg from android_logs
+ const rowsResult = await engine.query(`
+ select
+ ts,
+ prio,
+ ifnull(tag, '[NULL]') as tag,
+ ifnull(msg, '[NULL]') as msg
+ from android_logs
where ${vizSqlBounds}
order by ts
- limit ${pagination.start}, ${pagination.count}`);
+ limit ${pagination.start}, ${pagination.count}
+ `);
- if (!slowlyCountRows(rowsResult)) {
- return {
- offset: pagination.start,
- timestamps: [],
- priorities: [],
- tags: [],
- messages: [],
- };
+ const timestamps = [];
+ const priorities = [];
+ const tags = [];
+ const messages = [];
+
+ const it = rowsResult.iter({ts: NUM, prio: NUM, tag: STR, msg: STR});
+ for (; it.valid(); it.next()) {
+ timestamps.push(it.ts);
+ priorities.push(it.prio);
+ tags.push(it.tag);
+ messages.push(it.msg);
}
- const timestamps = rowsResult.columns[0].longValues!;
- const priorities = rowsResult.columns[1].longValues!;
- const tags = rowsResult.columns[2].stringValues!;
- const messages = rowsResult.columns[3].stringValues!;
-
return {
offset: pagination.start,
timestamps,
@@ -158,7 +170,7 @@
this.pagination = new Pagination(0, 0);
this.hasAnyLogs().then(exists => {
this.hasLogs = exists;
- this.app.publish('TrackData', {
+ publishTrackData({
id: LogExistsKey,
data: {
exists,
@@ -168,10 +180,10 @@
}
async hasAnyLogs() {
- const result = await this.engine.queryOneRow(`
- select count(*) from android_logs
+ const result = await this.engine.query(`
+ select count(*) as cnt from android_logs
`);
- return result[0] > 0;
+ return result.firstRow({cnt: NUM}).cnt > 0;
}
run() {
@@ -202,7 +214,7 @@
this.span = newSpan;
updateLogBounds(this.engine, newSpan).then(data => {
if (!newSpan.equals(this.span)) return;
- this.app.publish('TrackData', {
+ publishTrackData({
id: LogBoundsKey,
data,
});
@@ -216,7 +228,7 @@
updateLogEntries(this.engine, newSpan, this.pagination).then(data => {
if (!this.pagination.contains(requestedPagination)) return;
- this.app.publish('TrackData', {
+ publishTrackData({
id: LogEntriesKey,
data,
});
diff --git a/ui/src/controller/metrics_controller.ts b/ui/src/controller/metrics_controller.ts
index 6d0e835..92afb8a 100644
--- a/ui/src/controller/metrics_controller.ts
+++ b/ui/src/controller/metrics_controller.ts
@@ -13,8 +13,9 @@
// limitations under the License.
import {Actions} from '../common/actions';
-import {Engine, QueryError} from '../common/engine';
-import {iter, STR} from '../common/query_iterator';
+import {Engine} from '../common/engine';
+import {QueryError, STR} from '../common/query_result';
+import {publishMetricResult} from '../frontend/publish';
import {Controller} from './controller';
import {globals} from './globals';
@@ -33,13 +34,10 @@
private async getMetricNames() {
const metrics = [];
- const it = iter(
- {
- name: STR,
- },
- await this.engine.query('select name from trace_metrics'));
+ const result = await this.engine.query('select name from trace_metrics');
+ const it = result.iter({name: STR});
for (; it.valid(); it.next()) {
- metrics.push(it.row.name);
+ metrics.push(it.name);
}
return metrics;
}
@@ -54,14 +52,15 @@
this.currentlyRunningMetric = name;
try {
const metricResult = await this.engine.computeMetric([name]);
- globals.publish(
- 'MetricResult',
- {name, resultString: metricResult.metricsAsPrototext});
+ publishMetricResult({
+ 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});
+ publishMetricResult({name, error: e.message});
} else {
throw e;
}
diff --git a/ui/src/controller/permalink_controller.ts b/ui/src/controller/permalink_controller.ts
index f20cb18..3c48d16 100644
--- a/ui/src/controller/permalink_controller.ts
+++ b/ui/src/controller/permalink_controller.ts
@@ -25,10 +25,12 @@
saveTrace,
toSha256
} from '../common/upload_utils';
+import {publishConversionJobStatusUpdate} from '../frontend/publish';
+import {Router} from '../frontend/router';
import {Controller} from './controller';
import {globals} from './globals';
-import {validateRecordConfig} from './validate_config';
+import {JsonObject, validateRecordConfig} from './validate_config';
export class PermalinkController extends Controller<'main'> {
private lastRequestId?: string;
@@ -50,7 +52,7 @@
assertExists(globals.state.permalink.isRecordingConfig);
const jobName = 'create_permalink';
- globals.publish('ConversionJobStatusUpdate', {
+ publishConversionJobStatusUpdate({
jobName,
jobStatus: ConversionJobStatus.InProgress,
});
@@ -60,7 +62,7 @@
globals.dispatch(Actions.setPermalink({requestId, hash}));
})
.finally(() => {
- globals.publish('ConversionJobStatusUpdate', {
+ publishConversionJobStatusUpdate({
jobName,
jobStatus: ConversionJobStatus.NotRunning,
});
@@ -74,14 +76,10 @@
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'}));
+ const validConfig =
+ validateRecordConfig(stateOrConfig as unknown as JsonObject);
+ globals.dispatch(Actions.setRecordConfig({config: validConfig}));
+ Router.navigate('#!/record');
return;
}
globals.dispatch(Actions.setState({newState: stateOrConfig}));
diff --git a/ui/src/controller/pivot_table_controller.ts b/ui/src/controller/pivot_table_controller.ts
new file mode 100644
index 0000000..78abb24
--- /dev/null
+++ b/ui/src/controller/pivot_table_controller.ts
@@ -0,0 +1,755 @@
+// 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 {Actions} from '../common/actions';
+import {Engine} from '../common/engine';
+import {
+ AggregationAttrs,
+ AVAILABLE_AGGREGATIONS,
+ AVAILABLE_TABLES,
+ getDescendantsTables,
+ getParentStackColumn,
+ getStackColumn,
+ getStackDepthColumn,
+ PivotAttrs,
+ PivotTableQueryResponse,
+ removeHiddenAndAddStackColumns,
+ RowAttrs,
+ WHERE_FILTERS
+} from '../common/pivot_table_common';
+import {
+ getAggregationAlias,
+ getAggregationOverStackAlias,
+ getAliasedPivotColumns,
+ getHiddenPivotAlias,
+ getPivotAlias,
+ getTotalAggregationAlias,
+ PivotTableQueryGenerator
+} from '../common/pivot_table_query_generator';
+import {
+ QueryResponse,
+ runQuery,
+} from '../common/queries';
+import {Row} from '../common/query_result';
+import {toNs} from '../common/time';
+import {PivotTableHelper} from '../frontend/pivot_table_helper';
+import {publishPivotTableHelper, publishQueryResult} from '../frontend/publish';
+
+import {Controller} from './controller';
+import {globals} from './globals';
+
+export interface PivotTableControllerArgs {
+ pivotTableId: string;
+ engine: Engine;
+}
+
+function getExpandableColumn(
+ pivotTableId: string, queriedPivots: PivotAttrs[]): string|undefined {
+ if (queriedPivots.length === 0) {
+ return undefined;
+ }
+ const selectedPivots = globals.state.pivotTable[pivotTableId].selectedPivots;
+ const lastPivot = getPivotAlias(selectedPivots[selectedPivots.length - 1]);
+ const lastQueriedPivot =
+ getPivotAlias(queriedPivots[queriedPivots.length - 1]);
+ if (lastQueriedPivot !== lastPivot) {
+ return lastQueriedPivot;
+ }
+ return undefined;
+}
+
+function getRowWhereFilters(
+ queriedPivots: PivotAttrs[], row: Row, parentRow?: RowAttrs) {
+ let whereFilters = new Map();
+
+ // Add all the row's parent whereFilers.
+ if (parentRow) {
+ whereFilters = new Map(parentRow.whereFilters);
+ }
+
+ // Add whereFilters for all the queried pivots and any hidden pivots without
+ // the stack pivots.
+ getAliasedPivotColumns(queriedPivots)
+ .filter(pivot => !pivot.pivotAttrs.isStackPivot)
+ .forEach(
+ pivot => whereFilters.set(
+ pivot.columnAlias,
+ `CAST(${pivot.pivotAttrs.tableName}.${
+ pivot.pivotAttrs.columnName} AS TEXT) = '${
+ row[pivot.columnAlias]!.toString()}'`));
+
+ return whereFilters;
+}
+
+function getPivotTableQueryResponseRows(
+ pivotTableId: string,
+ rows: Row[],
+ queriedPivots: PivotAttrs[],
+ parentRow?: RowAttrs) {
+ const expandableColumns = new Set<string>();
+ if (queriedPivots.length > 0 && queriedPivots[0].isStackPivot) {
+ // Make the stack column expandable.
+ expandableColumns.add(getPivotAlias(queriedPivots[0]));
+ }
+ // Add expandable column after the stack column if it exists.
+ const expandableColumn = getExpandableColumn(pivotTableId, queriedPivots);
+ if (expandableColumn !== undefined) {
+ expandableColumns.add(expandableColumn);
+ }
+
+ const newRows: RowAttrs[] = [];
+ for (const row of rows) {
+ newRows.push({
+ row,
+ expandableColumns,
+ depth: 0,
+ whereFilters: getRowWhereFilters(queriedPivots, row, parentRow),
+ expandedRows: new Map()
+ });
+ }
+ return newRows;
+}
+
+function getPivotTableQueryResponse(
+ pivotTableId: string,
+ queryResp: QueryResponse,
+ queriedPivots: PivotAttrs[],
+ parentRow?: RowAttrs): PivotTableQueryResponse {
+ const columns = [];
+ const pivotTable = globals.state.pivotTable[pivotTableId];
+
+ for (let i = 0; i < pivotTable.selectedPivots.length; ++i) {
+ const pivot = pivotTable.selectedPivots[i];
+ columns.push({
+ name: getPivotAlias(pivot),
+ index: i,
+ tableName: pivot.tableName,
+ columnName: pivot.columnName,
+ isStackColumn: pivot.isStackPivot
+ });
+ }
+
+ for (let i = 0; i < pivotTable.selectedAggregations.length; ++i) {
+ const aggregation = pivotTable.selectedAggregations[i];
+ columns.push({
+ name: getAggregationAlias(aggregation),
+ index: i,
+ tableName: aggregation.tableName,
+ columnName: aggregation.columnName,
+ aggregation: aggregation.aggregation,
+ order: aggregation.order,
+ isStackColumn: false
+ });
+ }
+
+ return {
+ columns,
+ rows: getPivotTableQueryResponseRows(
+ pivotTableId, queryResp.rows, queriedPivots, parentRow),
+ error: queryResp.error,
+ durationMs: queryResp.durationMs
+ };
+}
+
+function getRowInPivotTableQueryResponse(
+ queryResp: PivotTableQueryResponse,
+ rowIndices: number[],
+ expandedRowColumns: string[]) {
+ if (rowIndices.length === 0) {
+ throw new Error('Row indicies should have at least one index.');
+ }
+
+ let row = queryResp.rows[rowIndices[0]];
+
+ // expandedRowColumns and rowIndices should refer to the same rows minus the
+ // initial row index that specifies the row in the query response.
+ if (rowIndices.length !== expandedRowColumns.length + 1) {
+ throw Error(`expandedRowColumns length "${
+ expandedRowColumns.length}" should be less than rowIndicies length "${
+ rowIndices.length}" by one.`);
+ }
+
+ for (let i = 1; i < rowIndices.length; ++i) {
+ const expandedRow = row.expandedRows.get(expandedRowColumns[i - 1]);
+ if (expandedRow === undefined || expandedRow.rows.length <= rowIndices[i]) {
+ throw new Error(`Expanded row index "${rowIndices[i]}" at row column "${
+ expandedRowColumns[i - 1]}" is out of bounds.`);
+ }
+ row = expandedRow.rows[rowIndices[i]];
+ }
+ return row;
+}
+
+function getDescendantRows(
+ pivotTableId: string,
+ respRows: Row[],
+ parentRow: RowAttrs,
+ queriedPivots: PivotAttrs[],
+ queriedAggregations: AggregationAttrs[]) {
+ const stackPivot = queriedPivots[0];
+ if (stackPivot === undefined || !stackPivot.isStackPivot) {
+ throw Error('Queried pivot is not a stack pivot');
+ }
+
+ const stackIdColumn = getHiddenPivotAlias(getStackColumn(stackPivot));
+
+ const parentStackIdColumn =
+ getHiddenPivotAlias(getParentStackColumn(stackPivot));
+
+ const depthColumn = getHiddenPivotAlias(getStackDepthColumn(stackPivot));
+
+ const stackColumn = getPivotAlias(stackPivot); // "name (stack)" column.
+
+ const parentDepth = Number(parentRow.row[depthColumn]?.toString());
+ if (!Number.isInteger(parentDepth)) {
+ throw Error('Parent row has undefined depth.');
+ }
+
+ const parentRowStackId = parentRow.row[stackIdColumn]?.toString();
+ if (parentRowStackId === undefined) {
+ throw Error('Parent row has undefined stack_id.');
+ }
+
+ const nextPivot = queriedPivots[1];
+ let nextColumnName = '';
+ if (nextPivot !== undefined) {
+ nextColumnName = getPivotAlias(nextPivot);
+ }
+
+ const newRows: Map<string, RowAttrs> = new Map();
+ for (const row of respRows) {
+ const depth = Number(row[depthColumn]?.toString());
+ const stackId = row[stackIdColumn]?.toString();
+ const parentStackId = row[parentStackIdColumn]?.toString();
+ if (!Number.isInteger(depth)) {
+ throw Error('Descendant result has undefined depth.');
+ }
+ if (!stackId || !parentStackId) {
+ throw Error('Descendant result has undefined stack or parent stack id.');
+ }
+
+ const expandableColumns = new Set<string>();
+ // Get expandable column after the stack column if it exists.
+ const expandableColumn = getExpandableColumn(pivotTableId, queriedPivots);
+ if (expandableColumn !== undefined) {
+ expandableColumns.add(expandableColumn);
+ }
+
+ const newRow: RowAttrs = {
+ row: Object.assign({}, row),
+ depth: depth - parentDepth,
+ whereFilters: getRowWhereFilters(queriedPivots, row, parentRow),
+ expandedRows: new Map(),
+ expandableColumns
+ };
+
+ // If we have already added the stackId, we need to extract and nest its
+ // next column values in its expanded rows.
+ if (newRows.has(stackId)) {
+ newRow.row[stackColumn] = null;
+ const parent = newRows.get(stackId)!;
+ let nextColumnRows = parent.expandedRows.get(nextColumnName);
+ if (nextColumnRows === undefined) {
+ // Since the parent row has more than one value for the next column,
+ // we nest the values in rows under the parent row instead of inline
+ // with it.
+ // Making a new row to hold the next column value.
+ const row = Object.assign({}, parent.row);
+ const nextColumnRow: RowAttrs = {
+ row: Object.assign({}, row),
+ depth: depth - parentDepth,
+ whereFilters: getRowWhereFilters(queriedPivots, row, parentRow),
+ expandedRows: new Map(),
+ expandableColumns
+ };
+ parent.row[nextColumnName] = null;
+ // Modify the parent row to show the aggregation over stack rows instead
+ // of the partitioned aggregations.
+ for (const aggregation of queriedAggregations) {
+ parent.row[getAggregationAlias(aggregation)] =
+ parent.row[getAggregationOverStackAlias(aggregation)];
+ }
+ nextColumnRow.row[stackColumn] = null;
+ if (nextColumnRow.row[nextColumnName] !== undefined) {
+ parent.expandedRows.set(
+ nextColumnName, {isExpanded: true, rows: [nextColumnRow]});
+ }
+ nextColumnRows = parent.expandedRows.get(nextColumnName);
+ }
+ newRow.expandableColumns = expandableColumns;
+
+ nextColumnRows!.rows.push(newRow);
+ }
+
+ // If we have already added the parentStackId, we need to nest the row
+ // in its parent's expanded rows.
+ // This works because we sort the result of the descendants query by
+ // depth, insuring that if the stack_id has a parent other than the
+ // parent row, its parent will show up first.
+ if (newRows.has(parentStackId)) {
+ const parent = newRows.get(parentStackId)!;
+ let descendants = parent.expandedRows.get(stackColumn);
+ if (descendants === undefined) {
+ parent.expandedRows.set(stackColumn, {isExpanded: true, rows: []});
+ descendants = parent.expandedRows.get(stackColumn);
+ }
+ descendants!.rows.push(newRow);
+ parent.expandableColumns.add(stackColumn);
+
+ // Unexpand if parent has more than one child.
+ if (descendants!.rows.length > 1) {
+ descendants!.isExpanded = false;
+ if (parent.expandedRows.has(nextColumnName)) {
+ parent.expandedRows.get(nextColumnName)!.isExpanded = false;
+ }
+ }
+ }
+
+ if (!newRows.has(stackId)) {
+ newRows.set(stackId, newRow);
+ }
+ }
+
+ // Get only direct descendants of the parent row. The rest is nested inside
+ // the descendants.
+ const descendantRows =
+ Array.from(newRows.values())
+ .filter(
+ row => row.row[parentStackIdColumn]?.toString() ===
+ parentRowStackId);
+ // Get the next column values of the parent row.
+ let nextColumnRows;
+ if (newRows.has(parentRowStackId)) {
+ if (newRows.get(parentRowStackId)!.expandedRows.has(nextColumnName)) {
+ nextColumnRows =
+ newRows.get(parentRowStackId)!.expandedRows.get(nextColumnName)!.rows;
+ } else {
+ // If the next column value is inline with the parent row.
+ nextColumnRows = [newRows.get(parentRowStackId)!];
+ }
+ }
+ return {descendantRows, nextColumnRows};
+}
+
+function getPivotColumns(
+ pivotTableId: string, columnIdx: number, isStackQuery: boolean) {
+ const selectedPivots = globals.state.pivotTable[pivotTableId].selectedPivots;
+ // Slice returns the pivot at columnIdx if it exists, and an empty
+ // array if columnIdx is out of bounds.
+ const pivots = selectedPivots.slice(columnIdx, columnIdx + 1);
+ if (isStackQuery) {
+ // Adds the next pivot, if it exists, to be queried with the stack query.
+ pivots.push(...selectedPivots.slice(columnIdx + 1, columnIdx + 2));
+ }
+ return pivots;
+}
+
+function getWhereFilters(
+ pivotTableId: string,
+ parentRowWhereFilters: Map<string, string>,
+ pivots: PivotAttrs[],
+ isStackQuery: boolean) {
+ const whereFiltersMap = new Map(parentRowWhereFilters);
+
+ // Remove any existing where filters for the pivots to query.
+ getAliasedPivotColumns(pivots).forEach(
+ pivotAlias => whereFiltersMap.delete(pivotAlias.columnAlias));
+
+ const whereFilters = Array.from(whereFiltersMap.values());
+
+ if (pivots.length > 0 && pivots[0].isStackPivot && !isStackQuery) {
+ // Only query top level slices, descendants can be generated
+ // when expanded.
+ const orderColumn = getStackDepthColumn(pivots[0]);
+ whereFilters.push(`${orderColumn.tableName}.${orderColumn.columnName} = 0`);
+ }
+
+ // Add global where filters
+ whereFilters.push(...WHERE_FILTERS);
+
+ // Add area restrictions where filters if set.
+ const pivotTable = globals.state.pivotTable[pivotTableId];
+ if (pivotTable.selectedTrackIds) {
+ whereFilters.push(`slice.track_id IN (${pivotTable.selectedTrackIds})`);
+ }
+ if (pivotTable.traceTime) {
+ whereFilters.push(
+ `slice.ts + slice.dur > ${toNs(pivotTable.traceTime.startSec)}`);
+ whereFilters.push(`slice.ts < ${toNs(pivotTable.traceTime.endSec)}`);
+ }
+
+ return whereFilters;
+}
+
+export class PivotTableController extends Controller<'main'> {
+ private pivotTableId: string;
+ private pivotTableQueryGenerator = new PivotTableQueryGenerator();
+ private engine: Engine;
+ private queryResp?: PivotTableQueryResponse;
+
+ constructor(args: PivotTableControllerArgs) {
+ super('main');
+ this.engine = args.engine;
+ this.pivotTableId = args.pivotTableId;
+ this.setup().then(() => {
+ this.run();
+ });
+ }
+
+ run() {
+ const {requestedAction} = globals.state.pivotTable[this.pivotTableId];
+ const pivotTable = globals.state.pivotTable[this.pivotTableId];
+ if (!requestedAction) return;
+ globals.dispatch(
+ Actions.resetPivotTableRequest({pivotTableId: this.pivotTableId}));
+ switch (requestedAction.action) {
+ case 'DESCENDANTS':
+ const descendantsAttrs = requestedAction.attrs;
+ if (descendantsAttrs === undefined) {
+ throw Error('No attributes provided for descendants query.');
+ }
+ if (this.queryResp === undefined) {
+ throw Error(
+ 'Descendants query requested without setting the main query.');
+ }
+
+ const stackPivot =
+ pivotTable.selectedPivots[descendantsAttrs.columnIdx];
+ const stackColumnName = getPivotAlias(stackPivot);
+
+ const nextPivot =
+ pivotTable.selectedPivots[descendantsAttrs.columnIdx + 1];
+ let nextColumnName = '';
+ if (nextPivot !== undefined) {
+ nextColumnName = getPivotAlias(nextPivot);
+ }
+
+ const ancestorRow = getRowInPivotTableQueryResponse(
+ this.queryResp,
+ descendantsAttrs.rowIndices,
+ descendantsAttrs.expandedRowColumns);
+
+ // No need to query if the row has been expanded before.
+ if (ancestorRow.expandedRows.has(stackColumnName)) {
+ ancestorRow.expandedRows.get(stackColumnName)!.isExpanded = true;
+ if (ancestorRow.expandedRows.has(nextColumnName) &&
+ !ancestorRow.expandableColumns.has(nextColumnName)) {
+ ancestorRow.expandedRows.get(nextColumnName)!.isExpanded = true;
+ }
+ break;
+ }
+
+ const descendantsPivots = getPivotColumns(
+ this.pivotTableId,
+ descendantsAttrs.columnIdx,
+ /* is_stack_query = */ true);
+
+ if (descendantsPivots.length === 0) {
+ throw Error(
+ `Descendant operation at column index "${
+ descendantsAttrs
+ .columnIdx}" should only be allowed if there are` +
+ `are more columns to query.`);
+ }
+
+ const descendantsWhereFilters = getWhereFilters(
+ this.pivotTableId,
+ ancestorRow.whereFilters,
+ descendantsPivots,
+ /* is_stack_query = */ true);
+
+ const stackIdColumn = getHiddenPivotAlias(getStackColumn(stackPivot));
+
+ const stackId = ancestorRow.row[stackIdColumn]?.toString();
+ if (stackId === undefined) {
+ throw Error(`"${
+ getPivotAlias(
+ stackPivot)}" row has undefined stack id at column "${
+ stackIdColumn}".`);
+ }
+
+ const descendantsTables =
+ getDescendantsTables(descendantsPivots, stackId);
+
+ // Query the descendants and the next column if it exists.
+ const descendantsQuery =
+ this.pivotTableQueryGenerator.generateStackQuery(
+ descendantsPivots,
+ pivotTable.selectedAggregations,
+ descendantsWhereFilters,
+ descendantsTables,
+ stackId);
+
+ ancestorRow.loadingColumn = stackColumnName;
+
+ runQuery(this.pivotTableId, descendantsQuery, this.engine)
+ .then(resp => {
+ // Query resulting from query generator should always be valid.
+ if (resp.error) {
+ throw Error(`Pivot table descendants query ${
+ descendantsQuery} resulted in SQL error: ${resp.error}`);
+ }
+
+ const printDescendantsQuery =
+ descendantsQuery.length <= 1024 ? descendantsQuery : '';
+ console.log(`Descendants query${printDescendantsQuery} took ${
+ resp.durationMs} ms`);
+
+ const {descendantRows, nextColumnRows} = getDescendantRows(
+ this.pivotTableId,
+ resp.rows,
+ ancestorRow,
+ descendantsPivots,
+ pivotTable.selectedAggregations);
+ // Set descendant rows.
+ ancestorRow.expandedRows.set(
+ stackColumnName, {isExpanded: true, rows: descendantRows});
+ // Set the next pivot row(s), if they exist, inside the parent
+ // row.
+ if (nextColumnRows !== undefined) {
+ if (nextColumnRows.length <= 1) {
+ // If there is only one value for the next column of the
+ // parent row, add it to the same row as the parent.
+ ancestorRow.row = nextColumnRows[0].row;
+ ancestorRow.expandableColumns = new Set([
+ ...nextColumnRows[0].expandableColumns,
+ ...ancestorRow.expandableColumns
+ ]);
+ } else {
+ ancestorRow.expandedRows.set(
+ nextColumnName, {isExpanded: true, rows: nextColumnRows});
+ }
+ }
+ ancestorRow.loadingColumn = undefined;
+
+ this.queryResp!.durationMs += resp.durationMs;
+ });
+ break;
+
+ case 'EXPAND':
+ const expandAttrs = requestedAction.attrs;
+ if (expandAttrs === undefined) {
+ throw Error('No attributes provided for expand query.');
+ }
+ if (this.queryResp === undefined) {
+ throw Error('Expand query requested without setting the main query.');
+ }
+
+ const expandColumnName =
+ getPivotAlias(pivotTable.selectedPivots[expandAttrs.columnIdx]);
+
+ const expandRow = getRowInPivotTableQueryResponse(
+ this.queryResp,
+ expandAttrs.rowIndices,
+ expandAttrs.expandedRowColumns);
+
+ // No need to query if the row has been expanded before.
+ if (expandRow.expandedRows.has(expandColumnName)) {
+ expandRow.expandedRows.get(expandColumnName)!.isExpanded = true;
+ break;
+ }
+
+ const expandPivots = getPivotColumns(
+ this.pivotTableId,
+ expandAttrs.columnIdx + 1,
+ /* is_stack_query = */ false);
+
+ if (expandPivots.length === 0) {
+ throw Error(
+ `Expand operation at column index "${
+ expandAttrs.columnIdx}" should only be allowed if there are` +
+ `are more columns to query.`);
+ }
+
+ const expandWhereFilters = getWhereFilters(
+ this.pivotTableId,
+ expandRow.whereFilters,
+ expandPivots,
+ /* is_stack_query = */ false);
+
+ const expandQuery = this.pivotTableQueryGenerator.generateQuery(
+ expandPivots,
+ pivotTable.selectedAggregations,
+ expandWhereFilters,
+ AVAILABLE_TABLES);
+
+ expandRow.loadingColumn =
+ getPivotAlias(pivotTable.selectedPivots[expandAttrs.columnIdx]);
+
+ runQuery(this.pivotTableId, expandQuery, this.engine).then(resp => {
+ // Query resulting from query generator should always be valid.
+ if (resp.error) {
+ throw Error(`Pivot table expand query ${
+ expandQuery} resulted in SQL error: ${resp.error}`);
+ }
+ const printExpandQuery =
+ expandQuery.length <= 1024 ? expandQuery : '';
+ console.log(
+ `Expand query${printExpandQuery} took ${resp.durationMs} ms`);
+
+ expandRow.expandedRows.set(expandColumnName, {
+ isExpanded: true,
+ rows: getPivotTableQueryResponseRows(
+ this.pivotTableId, resp.rows, expandPivots, expandRow)
+ });
+ expandRow.loadingColumn = undefined;
+
+ this.queryResp!.durationMs += resp.durationMs;
+ });
+ break;
+
+ case 'UNEXPAND':
+ const unexpandAttrs = requestedAction.attrs;
+ if (unexpandAttrs === undefined) {
+ throw Error('No attributes provided for unexpand query.');
+ }
+ if (this.queryResp === undefined) {
+ throw Error(
+ 'Unexpand query requested without setting the main query.');
+ }
+
+ const unexpandPivot =
+ pivotTable.selectedPivots[unexpandAttrs.columnIdx];
+ const unexpandColumnName = getPivotAlias(unexpandPivot);
+
+ const unexpandRow = getRowInPivotTableQueryResponse(
+ this.queryResp,
+ unexpandAttrs.rowIndices,
+ unexpandAttrs.expandedRowColumns);
+
+ if (unexpandRow.expandedRows.has(unexpandColumnName)) {
+ unexpandRow.expandedRows.get(unexpandColumnName)!.isExpanded = false;
+ const nextPivot =
+ pivotTable.selectedPivots[unexpandAttrs.columnIdx + 1];
+ let nextColumnName = '';
+ if (nextPivot !== undefined) {
+ nextColumnName = getPivotAlias(nextPivot);
+ }
+ // Unexpand the next column rows if they are nested inside the
+ // parent expanded row, but no expandable column exists for the
+ // next column.
+ if (unexpandPivot.isStackPivot &&
+ unexpandRow.expandedRows.has(nextColumnName) &&
+ !unexpandRow.expandableColumns.has(nextColumnName)) {
+ unexpandRow.expandedRows.get(nextColumnName)!.isExpanded = false;
+ }
+ } else {
+ throw Error('Unexpand request called on already undexpanded row.');
+ }
+ break;
+
+ case 'QUERY':
+ // Generates and executes new query based on selectedPivots and
+ // selectedAggregations.
+
+ const pivots = getPivotColumns(
+ this.pivotTableId,
+ /* column_idx = */ 0,
+ /* is_stack_query = */ false);
+
+ const whereFilers = getWhereFilters(
+ this.pivotTableId,
+ /*parent_row_where_Filters = */ new Map(),
+ pivots,
+ /* is_stack_query = */ false);
+
+ const query = this.pivotTableQueryGenerator.generateQuery(
+ pivots,
+ pivotTable.selectedAggregations,
+ whereFilers,
+ AVAILABLE_TABLES);
+
+ if (query !== '') {
+ globals.dispatch(
+ Actions.toggleQueryLoading({pivotTableId: this.pivotTableId}));
+ runQuery(this.pivotTableId, query, this.engine).then(resp => {
+ // Query resulting from query generator should always be valid.
+ if (resp.error) {
+ throw Error(`Pivot table query ${query} resulted in SQL error: ${
+ resp.error}`);
+ }
+
+ const printQuery = query.length <= 1024 ? query : '';
+ console.log(`Query${printQuery} took ${resp.durationMs} ms`);
+ const data =
+ getPivotTableQueryResponse(this.pivotTableId, resp, pivots);
+
+ if (pivotTable.selectedAggregations.length > 0 &&
+ resp.rows.length > 0) {
+ const totalAggregationsRow = Object.assign({}, resp.rows[0]);
+
+ // Modify the total aggregations row to show the total
+ // aggregations.
+ if (pivotTable.selectedPivots.length > 0) {
+ for (const aggregation of pivotTable.selectedAggregations) {
+ totalAggregationsRow[getAggregationAlias(aggregation)] =
+ totalAggregationsRow[getTotalAggregationAlias(
+ aggregation)];
+ }
+ }
+ data.totalAggregations = totalAggregationsRow;
+ }
+
+ publishQueryResult({id: this.pivotTableId, data});
+
+ this.queryResp = data;
+
+ globals.dispatch(
+ Actions.toggleQueryLoading({pivotTableId: this.pivotTableId}));
+ });
+ } else {
+ publishQueryResult({id: this.pivotTableId, data: undefined});
+ }
+ break;
+
+ default:
+ throw new Error(`Unexpected requested action ${requestedAction}`);
+ }
+ }
+
+ private async setup(): Promise<void> {
+ const pivotTable = globals.state.pivotTable[this.pivotTableId];
+ const selectedPivots = pivotTable.selectedPivots;
+ const selectedAggregations = pivotTable.selectedAggregations;
+ let availableColumns = globals.state.pivotTableConfig.availableColumns;
+ // No need to retrieve table columns if they are already stored.
+ // Only needed when first pivot table is created.
+ if (availableColumns === undefined) {
+ availableColumns = [];
+ for (const table of AVAILABLE_TABLES) {
+ const columns = await this.getColumnsForTable(table);
+ if (columns.length > 0) {
+ availableColumns.push({tableName: table, columns});
+ }
+ }
+ globals.dispatch(Actions.setAvailablePivotTableColumns(
+ {availableColumns, availableAggregations: AVAILABLE_AGGREGATIONS}));
+ }
+ publishPivotTableHelper({
+ id: this.pivotTableId,
+ data: new PivotTableHelper(
+ this.pivotTableId,
+ availableColumns,
+ AVAILABLE_AGGREGATIONS,
+ selectedPivots,
+ selectedAggregations)
+ });
+ }
+
+ private async getColumnsForTable(tableName: string): Promise<string[]> {
+ const query = `select * from ${tableName} limit 0;`;
+ const resp = await runQuery(this.pivotTableId, query, this.engine);
+ return removeHiddenAndAddStackColumns(tableName, resp.columns);
+ }
+}
diff --git a/ui/src/controller/query_controller.ts b/ui/src/controller/query_controller.ts
index c4bd9d4..b551a11 100644
--- a/ui/src/controller/query_controller.ts
+++ b/ui/src/controller/query_controller.ts
@@ -15,9 +15,8 @@
import {assertExists} from '../base/logging';
import {Actions} from '../common/actions';
import {Engine} from '../common/engine';
-import {rawQueryResultColumns, rawQueryResultIter, Row} from '../common/protos';
-import {QueryResponse} from '../common/queries';
-import {slowlyCountRows} from '../common/query_iterator';
+import {runQuery} from '../common/queries';
+import {publishQueryResult} from '../frontend/publish';
import {Controller} from './controller';
import {globals} from './globals';
@@ -36,11 +35,13 @@
switch (this.state) {
case 'init':
const config = assertExists(globals.state.queries[this.args.queryId]);
- this.runQuery(config.query).then(result => {
- console.log(`Query ${config.query} took ${result.durationMs} ms`);
- globals.publish('QueryResult', {id: this.args.queryId, data: result});
- globals.dispatch(Actions.deleteQuery({queryId: this.args.queryId}));
- });
+ runQuery(this.args.queryId, config.query, this.args.engine)
+ .then(result => {
+ console.log(`Query ${config.query} took ${result.durationMs} ms`);
+ publishQueryResult({id: this.args.queryId, data: result});
+ globals.dispatch(
+ Actions.deleteQuery({queryId: this.args.queryId}));
+ });
this.setState('querying');
break;
@@ -53,33 +54,4 @@
throw new Error(`Unexpected state ${this.state}`);
}
}
-
- private async runQuery(sqlQuery: string) {
- const startMs = performance.now();
- const rawResult = await this.args.engine.uncheckedQuery(sqlQuery);
- const durationMs = performance.now() - startMs;
- const columns = rawQueryResultColumns(rawResult);
- const rows =
- QueryController.firstN<Row>(10000, rawQueryResultIter(rawResult));
- const result: QueryResponse = {
- id: this.args.queryId,
- query: sqlQuery,
- durationMs,
- error: rawResult.error,
- totalRowCount: slowlyCountRows(rawResult),
- columns,
- rows,
- };
- return result;
- }
-
- private static firstN<T>(n: number, iter: IterableIterator<T>): T[] {
- const list = [];
- for (let i = 0; i < n; i++) {
- const {done, value} = iter.next();
- if (done) break;
- list.push(value);
- }
- return list;
- }
}
diff --git a/ui/src/controller/record_controller.ts b/ui/src/controller/record_controller.ts
index a124ecf..1b2c363 100644
--- a/ui/src/controller/record_controller.ts
+++ b/ui/src/controller/record_controller.ts
@@ -46,6 +46,7 @@
RecordConfig,
RecordingTarget
} from '../common/state';
+import {publishBufferUsage, publishTrackData} from '../frontend/publish';
import {AdbOverWebUsb} from './adb';
import {AdbConsumerPort} from './adb_shell_controller';
@@ -114,6 +115,8 @@
const atraceApps = new Set<string>();
const chromeCategories = new Set<string>();
uiCfg.chromeCategoriesSelected.forEach(it => chromeCategories.add(it));
+ uiCfg.chromeHighOverheadCategoriesSelected.forEach(
+ it => chromeCategories.add(it));
let procThreadAssociationPolling = false;
let procThreadAssociationFtrace = false;
@@ -122,6 +125,8 @@
if (uiCfg.cpuSched) {
procThreadAssociationPolling = true;
procThreadAssociationFtrace = true;
+ uiCfg.ftrace = true;
+ uiCfg.symbolizeKsyms = true;
ftraceEvents.add('sched/sched_switch');
ftraceEvents.add('power/suspend_resume');
ftraceEvents.add('sched/sched_wakeup');
@@ -430,10 +435,22 @@
metadataDs.config.chromeConfig = new ChromeConfig();
metadataDs.config.chromeConfig.traceConfig = traceConfigJson;
protoCfg.dataSources.push(metadataDs);
- }
- if (uiCfg.screenRecord) {
- atraceCats.add('gfx');
+ if (chromeCategories.has('disabled-by-default-memory-infra')) {
+ const memoryDs = new TraceConfig.DataSource();
+ memoryDs.config = new DataSourceConfig();
+ memoryDs.config.name = 'org.chromium.memory_instrumentation';
+ memoryDs.config.chromeConfig = new ChromeConfig();
+ memoryDs.config.chromeConfig.traceConfig = traceConfigJson;
+ protoCfg.dataSources.push(memoryDs);
+
+ const HeapProfDs = new TraceConfig.DataSource();
+ HeapProfDs.config = new DataSourceConfig();
+ HeapProfDs.config.name = 'org.chromium.native_heap_profiler';
+ HeapProfDs.config.chromeConfig = new ChromeConfig();
+ HeapProfDs.config.chromeConfig.traceConfig = traceConfigJson;
+ protoCfg.dataSources.push(HeapProfDs);
+ }
}
// Keep these last. The stages above can enrich them.
@@ -478,6 +495,10 @@
if (uiCfg.ftrace) {
ds.config.ftraceConfig.bufferSizeKb = uiCfg.ftraceBufferSizeKb;
ds.config.ftraceConfig.drainPeriodMs = uiCfg.ftraceDrainPeriodMs;
+ if (uiCfg.symbolizeKsyms) {
+ ds.config.ftraceConfig.symbolizeKsyms = true;
+ ftraceEvents.add('sched/sched_blocked_reason');
+ }
for (const line of uiCfg.ftraceExtraEvents.split('\n')) {
if (line.trim().length > 0) ftraceEvents.add(line.trim());
}
@@ -608,7 +629,7 @@
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.updateChromeCategories) {
if (this.app.state.extensionInstalled) {
this.extensionPort.postMessage({method: 'GetCategories'});
}
@@ -632,7 +653,7 @@
`;
const traceConfig = genConfig(this.config, this.app.state.recordingTarget);
// TODO(hjd): This should not be TrackData after we unify the stores.
- this.app.publish('TrackData', {
+ publishTrackData({
id: 'config',
data: {
commandline,
@@ -689,7 +710,7 @@
} else if (isGetTraceStatsResponse(data)) {
const percentage = this.getBufferUsagePercentage(data);
if (percentage) {
- globals.publish('BufferUsage', {percentage});
+ publishBufferUsage({percentage});
}
} else if (isFreeBuffersResponse(data)) {
// No action required.
diff --git a/ui/src/controller/record_controller_interfaces.ts b/ui/src/controller/record_controller_interfaces.ts
index 2dd2c91..501db75 100644
--- a/ui/src/controller/record_controller_interfaces.ts
+++ b/ui/src/controller/record_controller_interfaces.ts
@@ -15,7 +15,6 @@
import {TRACE_SUFFIX} from '../common/constants';
import {ConsumerPortResponse} from './consumer_port_types';
-export type ConsumerPortCallback = (_: ConsumerPortResponse) => void;
export type ErrorCallback = (_: string) => void;
export type StatusCallback = (_: string) => void;
diff --git a/ui/src/controller/record_controller_jsdomtest.ts b/ui/src/controller/record_controller_jsdomtest.ts
index 6d6e780..916054b 100644
--- a/ui/src/controller/record_controller_jsdomtest.ts
+++ b/ui/src/controller/record_controller_jsdomtest.ts
@@ -12,21 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {dingus} from 'dingusjs';
-
import {assertExists} from '../base/logging';
import {TraceConfig} from '../common/protos';
-import {createEmptyRecordConfig, RecordConfig} from '../common/state';
+import {createEmptyRecordConfig} from '../common/state';
-import {App} from './globals';
-import {genConfigProto, RecordController, toPbtxt} from './record_controller';
+import {genConfigProto, toPbtxt} from './record_controller';
test('encodeConfig', () => {
const config = createEmptyRecordConfig();
- config.durationSeconds = 10;
+ config.durationMs = 20000;
const result =
TraceConfig.decode(genConfigProto(config, {os: 'Q', name: 'Android Q'}));
- expect(result.durationMs).toBe(10000);
+ expect(result.durationMs).toBe(20000);
});
test('SysConfig', () => {
@@ -42,6 +39,47 @@
expect(ftraceEvents.includes('raw_syscalls/sys_exit')).toBe(true);
});
+test('cpu scheduling includes kSyms', () => {
+ const config = createEmptyRecordConfig();
+ config.cpuSched = true;
+ const result =
+ TraceConfig.decode(genConfigProto(config, {os: 'Q', name: 'Android Q'}));
+ const sources = assertExists(result.dataSources);
+ const srcConfig = assertExists(sources[1].config);
+ const ftraceConfig = assertExists(srcConfig.ftraceConfig);
+ const ftraceEvents = assertExists(ftraceConfig.ftraceEvents);
+ expect(ftraceConfig.symbolizeKsyms).toBe(true);
+ expect(ftraceEvents.includes('sched/sched_blocked_reason')).toBe(true);
+});
+
+test('kSyms can be enabled individually', () => {
+ const config = createEmptyRecordConfig();
+ config.ftrace = true;
+ config.symbolizeKsyms = true;
+ const result =
+ TraceConfig.decode(genConfigProto(config, {os: 'Q', name: 'Android Q'}));
+ const sources = assertExists(result.dataSources);
+ const srcConfig = assertExists(sources[0].config);
+ const ftraceConfig = assertExists(srcConfig.ftraceConfig);
+ const ftraceEvents = assertExists(ftraceConfig.ftraceEvents);
+ expect(ftraceConfig.symbolizeKsyms).toBe(true);
+ expect(ftraceEvents.includes('sched/sched_blocked_reason')).toBe(true);
+});
+
+test('kSyms can be disabled individually', () => {
+ const config = createEmptyRecordConfig();
+ config.ftrace = true;
+ config.symbolizeKsyms = false;
+ const result =
+ TraceConfig.decode(genConfigProto(config, {os: 'Q', name: 'Android Q'}));
+ const sources = assertExists(result.dataSources);
+ const srcConfig = assertExists(sources[0].config);
+ const ftraceConfig = assertExists(srcConfig.ftraceConfig);
+ const ftraceEvents = assertExists(ftraceConfig.ftraceEvents);
+ expect(ftraceConfig.symbolizeKsyms).toBe(false);
+ expect(ftraceEvents.includes('sched/sched_blocked_reason')).toBe(false);
+});
+
test('toPbtxt', () => {
const config = {
durationMs: 1000,
@@ -90,21 +128,6 @@
`);
});
-test('RecordController', () => {
- const app = dingus<App>('globals');
- (app.state.recordConfig as RecordConfig) = createEmptyRecordConfig();
- const m: MessageChannel = dingus<MessageChannel>('extensionPort');
- const controller = new RecordController({app, extensionPort: m.port1});
- controller.run();
- controller.run();
- controller.run();
- // tslint:disable-next-line no-any
- const calls = app.calls.filter((call: any) => call[0] === 'publish()');
- expect(calls.length).toBe(1);
- // TODO(hjd): Fix up dingus to have a more sensible API.
- expect(calls[0][1][0]).toEqual('TrackData');
-});
-
test('ChromeConfig', () => {
const config = createEmptyRecordConfig();
config.ipcFlows = true;
@@ -134,7 +157,8 @@
test('ChromeMemoryConfig', () => {
const config = createEmptyRecordConfig();
- config.chromeCategoriesSelected = ['disabled-by-default-memory-infra'];
+ config.chromeHighOverheadCategoriesSelected =
+ ['disabled-by-default-memory-infra'];
const result =
TraceConfig.decode(genConfigProto(config, {os: 'C', name: 'Chrome'}));
const sources = assertExists(result.dataSources);
@@ -149,12 +173,25 @@
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}]}}';
+ const miConfigSource = assertExists(sources[2].config);
+ expect(miConfigSource.name).toBe('org.chromium.memory_instrumentation');
+ const chromeConfigI = assertExists(miConfigSource.chromeConfig);
+ const traceConfigI = assertExists(chromeConfigI.traceConfig);
+
+ const hpConfigSource = assertExists(sources[3].config);
+ expect(hpConfigSource.name).toBe('org.chromium.native_heap_profiler');
+ const chromeConfigH = assertExists(hpConfigSource.chromeConfig);
+ const traceConfigH = assertExists(chromeConfigH.traceConfig);
+
+ const expectedTraceConfig = '{\"record_mode\":\"record-until-full\",' +
+ '\"included_categories\":[\"disabled-by-default-memory-infra\"],' +
+ '\"memory_dump_config\":{\"allowed_dump_modes\":[\"background\",' +
+ '\"light\",\"detailed\"],\"triggers\":[{\"min_time_between_dumps_ms\":' +
+ '10000,\"mode\":\"detailed\",\"type\":\"periodic_interval\"}]}}';
expect(traceConfigM).toEqual(expectedTraceConfig);
expect(traceConfig).toEqual(expectedTraceConfig);
+ expect(traceConfigI).toEqual(expectedTraceConfig);
+ expect(traceConfigH).toEqual(expectedTraceConfig);
});
test('ChromeConfigRingBuffer', () => {
@@ -184,7 +221,6 @@
expect(traceConfig).toEqual(expectedTraceConfig);
});
-
test('ChromeConfigLongTrace', () => {
const config = createEmptyRecordConfig();
config.ipcFlows = true;
diff --git a/ui/src/controller/search_controller.ts b/ui/src/controller/search_controller.ts
index 8f71701..3ec461f 100644
--- a/ui/src/controller/search_controller.ts
+++ b/ui/src/controller/search_controller.ts
@@ -14,9 +14,10 @@
import {TRACE_MARGIN_TIME_S} from '../common/constants';
import {Engine} from '../common/engine';
-import {NUM, STR} from '../common/query_iterator';
+import {NUM, STR} from '../common/query_result';
import {CurrentSearchResults, SearchSummary} from '../common/search_data';
import {TimeSpan} from '../common/time';
+import {publishSearch, publishSearchResult} from '../frontend/publish';
import {Controller} from './controller';
import {App} from './globals';
@@ -59,11 +60,11 @@
}
private async setup() {
- await this.queryV2(`create virtual table search_summary_window
+ await this.query(`create virtual table search_summary_window
using window;`);
- await this.queryV2(`create virtual table search_summary_sched_span using
+ await this.query(`create virtual table search_summary_sched_span using
span_join(sched PARTITIONED cpu, search_summary_window);`);
- await this.queryV2(`create virtual table search_summary_slice_span using
+ await this.query(`create virtual table search_summary_slice_span using
span_join(slice PARTITIONED track_id, search_summary_window);`);
}
@@ -92,12 +93,12 @@
this.previousResolution = newResolution;
this.previousSearch = newSearch;
if (newSearch === '' || newSearch.length < 4) {
- this.app.publish('Search', {
+ publishSearch({
tsStarts: new Float64Array(0),
tsEnds: new Float64Array(0),
count: new Uint8Array(0),
});
- this.app.publish('SearchResult', {
+ publishSearchResult({
sliceIds: new Float64Array(0),
tsStarts: new Float64Array(0),
utids: new Float64Array(0),
@@ -125,12 +126,12 @@
this.updateInProgress = true;
const computeSummary =
this.update(newSearch, startNs, endNs, newResolution).then(summary => {
- this.app.publish('Search', summary);
+ publishSearch(summary);
});
const computeResults =
this.specificSearch(newSearch).then(searchResults => {
- this.app.publish('SearchResult', searchResults);
+ publishSearchResult(searchResults);
});
Promise.all([computeSummary, computeResults])
@@ -151,13 +152,14 @@
startNs = Math.floor(startNs / quantumNs) * quantumNs;
- await this.queryV2(`update search_summary_window set
+ const windowDur = Math.max(endNs - startNs, 1);
+ await this.query(`update search_summary_window set
window_start=${startNs},
- window_dur=${endNs - startNs},
+ window_dur=${windowDur},
quantum=${quantumNs}
where rowid = 0;`);
- const utidRes = await this.queryV2(`select utid from thread join process
+ const utidRes = await this.query(`select utid from thread join process
using(upid) where thread.name like ${searchLiteral}
or process.name like ${searchLiteral}`);
@@ -169,7 +171,7 @@
const cpus = await this.engine.getCpus();
const maxCpu = Math.max(...cpus, -1);
- const res = await this.queryV2(`
+ const res = await this.query(`
select
(quantum_ts * ${quantumNs} + ${startNs})/1e9 as tsStart,
((quantum_ts+1) * ${quantumNs} + ${startNs})/1e9 as tsEnd,
@@ -229,7 +231,7 @@
}
}
- const utidRes = await this.queryV2(`select utid from thread join process
+ const utidRes = await this.query(`select utid from thread join process
using(upid) where
thread.name like ${searchLiteral} or
process.name like ${searchLiteral}`);
@@ -238,7 +240,7 @@
utids.push(it.utid);
}
- const queryRes = await this.queryV2(`
+ const queryRes = await this.query(`
select
id as sliceId,
ts,
@@ -267,17 +269,19 @@
where string_value like ${searchLiteral}
order by ts`);
+ const rows = queryRes.numRows();
const searchResults: CurrentSearchResults = {
- sliceIds: [],
- tsStarts: [],
- utids: [],
+ sliceIds: new Float64Array(rows),
+ tsStarts: new Float64Array(rows),
+ utids: new Float64Array(rows),
trackIds: [],
sources: [],
totalResults: queryRes.numRows(),
};
- const spec = {sliceId: NUM, ts: NUM, source: STR, sourceId: NUM, utid: NUM};
- for (const it = queryRes.iter(spec); it.valid(); it.next()) {
+ const it = queryRes.iter(
+ {sliceId: NUM, ts: NUM, source: STR, sourceId: NUM, utid: NUM});
+ for (let i = 0; it.valid(); it.next(), ++i) {
let trackId = undefined;
if (it.source === 'cpu') {
trackId = cpuToTrackId.get(it.sourceId);
@@ -292,15 +296,15 @@
}
searchResults.trackIds.push(trackId);
searchResults.sources.push(it.source);
- searchResults.sliceIds.push(it.sliceId);
- searchResults.tsStarts.push(it.ts);
- searchResults.utids.push(it.utid);
+ searchResults.sliceIds[i] = it.sliceId;
+ searchResults.tsStarts[i] = it.ts;
+ searchResults.utids[i] = it.utid;
}
return searchResults;
}
- private async queryV2(query: string) {
- const result = await this.engine.queryV2(query);
+ private async query(query: string) {
+ const result = await this.engine.query(query);
return result;
}
}
diff --git a/ui/src/controller/selection_controller.ts b/ui/src/controller/selection_controller.ts
index 0366df1..4bb8d45 100644
--- a/ui/src/controller/selection_controller.ts
+++ b/ui/src/controller/selection_controller.ts
@@ -12,23 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {assertTrue} from '../base/logging';
import {Arg, Args} from '../common/arg_types';
import {Engine} from '../common/engine';
import {
NUM,
- singleRow,
- singleRowUntyped,
- slowlyCountRows,
- STR
-} from '../common/query_iterator';
+ NUM_NULL,
+ STR,
+ STR_NULL,
+} from '../common/query_result';
import {ChromeSliceSelection} from '../common/state';
import {translateState} from '../common/thread_state';
import {fromNs, toNs} from '../common/time';
+import {SliceDetails, ThreadStateDetails} from '../frontend/globals';
import {
- CounterDetails,
- SliceDetails,
- ThreadStateDetails
-} from '../frontend/globals';
+ publishCounterDetails,
+ publishSliceDetails,
+ publishThreadStateDetails
+} from '../frontend/publish';
import {SLICE_TRACK_KIND} from '../tracks/chrome_slices/common';
import {parseArgs} from './args_parser';
@@ -68,14 +69,12 @@
if (selectedId === undefined) return;
if (selection.kind === 'COUNTER') {
- const selected: CounterDetails = {};
this.counterDetails(selection.leftTs, selection.rightTs, selection.id)
.then(results => {
if (results !== undefined && selection &&
selection.kind === selectedKind &&
selection.id === selectedId) {
- Object.assign(selected, results);
- globals.publish('CounterDetails', selected);
+ publishCounterDetails(results);
}
});
} else if (selection.kind === 'SLICE') {
@@ -101,23 +100,23 @@
promisedDescription = Promise.resolve(new Map());
promisedArgs = Promise.resolve(new Map());
} else {
- const typeResult = singleRow(
- {
- leafTable: STR,
- argSetId: NUM,
- },
- await this.args.engine.query(`
+ const result = await this.args.engine.query(`
SELECT
type as leafTable,
arg_set_id as argSetId
- FROM slice WHERE id = ${selectedId}`));
+ FROM slice WHERE id = ${selectedId}`);
- if (typeResult === undefined) {
+ if (result.numRows() === 0) {
return;
}
- leafTable = typeResult.leafTable;
- const argSetId = typeResult.argSetId;
+ const row = result.firstRow({
+ leafTable: STR,
+ argSetId: NUM,
+ });
+
+ leafTable = row.leafTable;
+ const argSetId = row.argSetId;
promisedDescription = this.describeSlice(selectedId);
promisedArgs = this.getArgs(argSetId);
}
@@ -129,10 +128,9 @@
const [details, args, description] =
await Promise.all([promisedDetails, promisedArgs, promisedDescription]);
- const row = singleRowUntyped(details);
- if (row === undefined) {
- return;
- }
+ if (details.numRows() <= 0) return;
+ const rowIter = details.iter({});
+ assertTrue(rowIter.valid());
// A few columns are hard coded as part of the SliceDetails interface.
// Long term these should be handled generically as args but for now
@@ -142,7 +140,8 @@
let name = undefined;
let category = undefined;
- for (const [k, v] of Object.entries(row)) {
+ for (const k of details.columns()) {
+ const v = rowIter.get(k);
switch (k) {
case 'id':
break;
@@ -178,7 +177,7 @@
// Check selection is still the same on completion of query.
if (selection === globals.state.currentSelection) {
- globals.publish('SliceDetails', selected);
+ publishSliceDetails(selected);
}
}
@@ -186,14 +185,17 @@
const map = new Map<string, string>();
if (id === -1) return map;
const query = `
- select description, doc_link
+ select
+ ifnull(description, '') as description,
+ ifnull(doc_link, '') as docLink
from describe_slice
where slice_id = ${id}
`;
const result = await this.args.engine.query(query);
- for (let i = 0; i < slowlyCountRows(result); i++) {
- const description = result.columns[0].stringValues![i];
- const docLink = result.columns[1].stringValues![i];
+ const it = result.iter({description: STR, docLink: STR});
+ for (; it.valid(); it.next()) {
+ const description = it.description;
+ const docLink = it.docLink;
map.set('Description', description);
map.set('Documentation', docLink);
}
@@ -210,9 +212,13 @@
WHERE arg_set_id = ${argId}
`;
const result = await this.args.engine.query(query);
- for (let i = 0; i < slowlyCountRows(result); i++) {
- const name = result.columns[0].stringValues![i];
- const value = result.columns[1].stringValues![i];
+ const it = result.iter({
+ name: STR,
+ value: STR,
+ });
+ for (; it.valid(); it.next()) {
+ const name = it.name;
+ const value = it.value;
if (name === 'destination slice id' && !isNaN(Number(value))) {
const destTrackId = await this.getDestTrackId(value);
args.set(
@@ -226,10 +232,10 @@
}
async getDestTrackId(sliceId: string): Promise<string> {
- const trackIdQuery = `select track_id from slice
+ const trackIdQuery = `select track_id as trackId from slice
where slice_id = ${sliceId}`;
- const destResult = await this.args.engine.query(trackIdQuery);
- const trackIdTp = destResult.columns[0].longValues![0];
+ const result = await this.args.engine.query(trackIdQuery);
+ const trackIdTp = result.firstRow({trackId: NUM}).trackId;
// TODO(hjd): If we had a consistent mapping from TP track_id
// UI track id for slice tracks this would be unnecessary.
let trackId = '';
@@ -247,101 +253,121 @@
const query = `
SELECT
ts,
- thread_state.dur,
+ thread_state.dur as dur,
state,
- io_wait,
- thread_state.utid,
- thread_state.cpu,
- sched.id,
- thread_state.blocked_function
+ io_wait as ioWait,
+ thread_state.utid as utid,
+ thread_state.cpu as cpu,
+ sched.id as id,
+ thread_state.blocked_function as blockedFunction
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);
- }
- });
+ const result = await this.args.engine.query(query);
+
+ const selection = globals.state.currentSelection;
+ if (result.numRows() > 0 && selection) {
+ const row = result.firstRow({
+ ts: NUM,
+ dur: NUM,
+ state: STR,
+ ioWait: NUM_NULL,
+ utid: NUM,
+ cpu: NUM_NULL,
+ id: NUM_NULL,
+ blockedFunction: STR_NULL,
+ });
+ const ts = row.ts;
+ const timeFromStart = fromNs(ts) - globals.state.traceTime.startSec;
+ const dur = fromNs(row.dur);
+ const ioWait = row.ioWait === null ? undefined : row.ioWait > 0;
+ const state = translateState(row.state, ioWait);
+ const utid = row.utid;
+ const cpu = row.cpu === null ? undefined : row.cpu;
+ const sliceId = row.id === null ? undefined : row.id;
+ const blockedFunction =
+ row.blockedFunction === null ? undefined : row.blockedFunction;
+ const selected: ThreadStateDetails =
+ {ts: timeFromStart, dur, state, utid, cpu, sliceId, blockedFunction};
+ publishThreadStateDetails(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)
+ const sqlQuery = `SELECT
+ ts,
+ dur,
+ priority,
+ end_state as endState,
+ utid,
+ cpu,
+ thread_state.id as threadStateId
+ FROM sched join thread_state using(ts, utid, dur, cpu)
WHERE sched.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];
- const timeFromStart = fromNs(ts) - globals.state.traceTime.startSec;
- const dur = fromNs(result.columns[1].longValues![0]);
- const priority = result.columns[2].longValues![0];
- 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
- };
- this.schedulingDetails(ts, utid)
- .then(wakeResult => {
- Object.assign(selected, wakeResult);
- })
- .finally(() => {
- globals.publish('SliceDetails', selected);
- });
- }
- });
+ const result = await this.args.engine.query(sqlQuery);
+ // Check selection is still the same on completion of query.
+ const selection = globals.state.currentSelection;
+ if (result.numRows() > 0 && selection) {
+ const row = result.firstRow({
+ ts: NUM,
+ dur: NUM,
+ priority: NUM,
+ endState: STR,
+ utid: NUM,
+ cpu: NUM,
+ threadStateId: NUM,
+ });
+ const ts = row.ts;
+ const timeFromStart = fromNs(ts) - globals.state.traceTime.startSec;
+ const dur = fromNs(row.dur);
+ const priority = row.priority;
+ const endState = row.endState;
+ const utid = row.utid;
+ const cpu = row.cpu;
+ const threadStateId = row.threadStateId;
+ const selected: SliceDetails = {
+ ts: timeFromStart,
+ dur,
+ priority,
+ endState,
+ cpu,
+ id,
+ utid,
+ threadStateId
+ };
+ this.schedulingDetails(ts, utid)
+ .then(wakeResult => {
+ Object.assign(selected, wakeResult);
+ })
+ .finally(() => {
+ publishSliceDetails(selected);
+ });
+ }
}
async counterDetails(ts: number, rightTs: number, id: number) {
const counter = await this.args.engine.query(
- `SELECT value, track_id FROM counter WHERE id = ${id}`);
- const value = counter.columns[0].doubleValues![0];
- const trackId = counter.columns[1].longValues![0];
+ `SELECT value, track_id as trackId FROM counter WHERE id = ${id}`);
+ const row = counter.iter({
+ value: NUM,
+ trackId: NUM,
+ });
+ const value = row.value;
+ const trackId = row.trackId;
// Finding previous value. If there isn't previous one, it will return 0 for
// ts and value.
- const previous = await this.args.engine.query(
- `SELECT MAX(ts), value FROM counter WHERE ts < ${ts} and track_id = ${
- trackId}`);
- const previousValue = previous.columns[1].doubleValues![0];
+ const previous = await this.args.engine.query(`SELECT
+ MAX(ts),
+ IFNULL(value, 0) as value
+ FROM counter WHERE ts < ${ts} and track_id = ${trackId}`);
+ const previousValue = previous.firstRow({value: NUM}).value;
const endTs =
rightTs !== -1 ? rightTs : toNs(globals.state.traceTime.endSec);
const delta = value - previousValue;
const duration = endTs - ts;
const startTime = fromNs(ts) - globals.state.traceTime.startSec;
- return {startTime, value, delta, duration};
+ const name = globals.state.tracks[trackId].name;
+ return {startTime, value, delta, duration, name};
}
async schedulingDetails(ts: number, utid: number|Long) {
@@ -350,8 +376,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.numRows() === 0) {
+ if (wakeup.numRows() === 0) return undefined;
// Only use sched_wakeup if waking is not in the trace.
event = 'sched_wakeup';
}
@@ -359,32 +385,37 @@
// Find the ts of the first sched_wakeup before the current slice.
const queryWakeupTs = `select ts from instants where name = '${event}'
and ref = ${utid} and ts < ${ts} order by ts desc limit 1`;
- const wakeupRow = await this.args.engine.queryOneRow(queryWakeupTs);
+ const wakeResult = await this.args.engine.query(queryWakeupTs);
+ if (wakeResult.numRows() === 0) {
+ return undefined;
+ }
+ const wakeupTs = wakeResult.firstRow({ts: NUM}).ts;
+
// Find the previous sched slice for the current utid.
const queryPrevSched = `select ts from sched where utid = ${utid}
and ts < ${ts} order by ts desc limit 1`;
- const prevSchedRow = await this.args.engine.queryOneRow(queryPrevSched);
+ const prevSchedResult = await this.args.engine.query(queryPrevSched);
+
// If this is the first sched slice for this utid or if the wakeup found
// was after the previous slice then we know the wakeup was for this slice.
- if (wakeupRow[0] === undefined ||
- (prevSchedRow[0] !== undefined && wakeupRow[0] < prevSchedRow[0])) {
+ if (prevSchedResult.numRows() === 0 ||
+ wakeupTs < prevSchedResult.firstRow({ts: NUM}).ts) {
return undefined;
}
- const wakeupTs = wakeupRow[0];
// Find the sched slice with the utid of the waker running when the
// sched wakeup occurred. This is the waker.
const queryWaker = `select utid, cpu from sched where utid =
(select utid from raw where name = '${event}' and ts = ${wakeupTs})
and ts < ${wakeupTs} and ts + dur >= ${wakeupTs};`;
- const wakerRow = await this.args.engine.queryOneRow(queryWaker);
- if (wakerRow) {
- return {
- wakeupTs: fromNs(wakeupTs),
- wakerUtid: wakerRow[0],
- wakerCpu: wakerRow[1]
- };
- } else {
+ const wakerResult = await this.args.engine.query(queryWaker);
+ if (wakerResult.numRows() === 0) {
return undefined;
}
+ const wakerRow = wakerResult.firstRow({utid: NUM, cpu: NUM});
+ return {
+ wakeupTs: fromNs(wakeupTs),
+ wakerUtid: wakerRow.utid,
+ wakerCpu: wakerRow.cpu
+ };
}
}
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 8427b7c..fd2b3b3 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -12,22 +12,32 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import '../tracks/all_controller';
-
import {assertExists, assertTrue} from '../base/logging';
import {
Actions,
DeferredAction,
} from '../common/actions';
+import {cacheTrace} from '../common/cache_manager';
import {TRACE_MARGIN_TIME_S} from '../common/constants';
-import {Engine, QueryError} from '../common/engine';
+import {Engine} from '../common/engine';
+import {featureFlags, Flag, PERF_SAMPLE_FLAG} from '../common/feature_flags';
import {HttpRpcEngine} from '../common/http_rpc_engine';
-import {slowlyCountRows} from '../common/query_iterator';
+import {NUM, NUM_NULL, QueryError, STR, STR_NULL} from '../common/query_result';
import {EngineMode} from '../common/state';
-import {toNs, toNsCeil, toNsFloor} from '../common/time';
-import {TimeSpan} from '../common/time';
-import {WasmEngineProxy} from '../common/wasm_engine_proxy';
-import {QuantizedLoad, ThreadDesc} from '../frontend/globals';
+import {TimeSpan, toNs, toNsCeil, toNsFloor} from '../common/time';
+import {resetEngineWorker, WasmEngineProxy} from '../common/wasm_engine_proxy';
+import {
+ globals as frontendGlobals,
+ QuantizedLoad,
+ ThreadDesc
+} from '../frontend/globals';
+import {
+ publishHasFtrace,
+ publishMetricError,
+ publishOverviewData,
+ publishThreads
+} from '../frontend/publish';
+import {Router} from '../frontend/router';
import {
CounterAggregationController
@@ -50,17 +60,21 @@
CpuProfileControllerArgs
} from './cpu_profile_controller';
import {
+ FlamegraphController,
+ FlamegraphControllerArgs
+} from './flamegraph_controller';
+import {
FlowEventsController,
FlowEventsControllerArgs
} from './flow_events_controller';
import {globals} from './globals';
-import {
- HeapProfileController,
- HeapProfileControllerArgs
-} from './heap_profile_controller';
import {LoadingManager} from './loading_manager';
import {LogsController} from './logs_controller';
import {MetricsController} from './metrics_controller';
+import {
+ PivotTableController,
+ PivotTableControllerArgs
+} from './pivot_table_controller';
import {QueryController, QueryControllerArgs} from './query_controller';
import {SearchController} from './search_controller';
import {
@@ -81,6 +95,31 @@
type States = 'init'|'loading_trace'|'ready';
+const METRICS = [
+ 'android_startup',
+ 'android_ion',
+ 'android_lmk',
+ 'android_dma_heap',
+ 'android_thread_time_in_state',
+ 'android_surfaceflinger',
+ 'android_batt',
+ 'android_sysui_cuj',
+ 'android_jank',
+ 'trace_metadata',
+];
+const FLAGGED_METRICS: Array<[Flag, string]> = METRICS.map(m => {
+ const id = `forceMetric${m}`;
+ let name = m.split('_').join(' ') + ' metric';
+ name = name[0].toUpperCase() + name.slice(1);
+ const flag = featureFlags.register({
+ id,
+ name,
+ description: `Overrides running the '${m}' metric at import time.`,
+ defaultValue: true,
+ });
+ return [flag, m];
+});
+
// 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
@@ -124,7 +163,6 @@
case 'ready':
// At this point we are ready to serve queries and handle tracks.
const engine = assertExists(this.engine);
- assertTrue(engineCfg.ready);
const childControllers: Children = [];
// Create a TrackController for each track.
@@ -155,9 +193,9 @@
childControllers.push(
Child('cpuProfile', CpuProfileController, cpuProfileArgs));
- const heapProfileArgs: HeapProfileControllerArgs = {engine};
+ const flamegraphArgs: FlamegraphControllerArgs = {engine};
childControllers.push(
- Child('heapProfile', HeapProfileController, heapProfileArgs));
+ Child('flamegraph', FlamegraphController, flamegraphArgs));
childControllers.push(Child(
'cpu_aggregation',
CpuAggregationController,
@@ -190,6 +228,15 @@
childControllers.push(
Child('traceError', TraceErrorController, {engine}));
childControllers.push(Child('metrics', MetricsController, {engine}));
+
+ // Create a PivotTableController for each pivot table.
+ for (const pivotTableId of Object.keys(globals.state.pivotTable)) {
+ const pivotTableArgs:
+ PivotTableControllerArgs = {pivotTableId, engine};
+ childControllers.push(
+ Child(pivotTableId, PivotTableController, pivotTableArgs));
+ }
+
return childControllers;
default:
@@ -221,7 +268,7 @@
} else {
console.log('Opening trace using built-in WASM engine');
engineMode = 'WASM';
- const enginePort = globals.resetEngineWorker();
+ const enginePort = resetEngineWorker();
this.engine = new WasmEngineProxy(
this.engineId, enginePort, LoadingManager.getInstance);
}
@@ -273,6 +320,9 @@
await this.engine.restoreInitialTables();
}
+ // traceUuid will be '' if the trace is not cacheable (URL or RPC).
+ const traceUuid = await this.cacheCurrentTrace();
+
const traceTime = await this.engine.getTraceTimeBounds();
let startSec = traceTime.start;
let endSec = traceTime.end;
@@ -282,9 +332,18 @@
startSec,
endSec,
};
+
+ const emptyOmniboxState = {
+ omnibox: '',
+ mode: frontendGlobals.state.frontendLocalState.omniboxState.mode ||
+ 'SEARCH',
+ lastUpdate: Date.now() / 1000
+ };
+
const actions: DeferredAction[] = [
- Actions.setTraceTime(traceTimeState),
- Actions.navigate({route: '/viewer'}),
+ Actions.setOmnibox(emptyOmniboxState),
+ Actions.setTraceUuid({traceUuid}),
+ Actions.setTraceTime(traceTimeState)
];
let visibleStartSec = startSec;
@@ -309,6 +368,7 @@
}));
globals.dispatchMultiple(actions);
+ Router.navigate(`#!/viewer?trace_id=${traceUuid}`);
// Make sure the helper views are available before we start adding tracks.
await this.initialiseHelperViews();
@@ -325,18 +385,47 @@
await this.loadTimelineOverview(traceTime);
{
- const query = 'select to_ftrace(id) from raw limit 1';
+ // A quick heuristic to check if the trace has ftrace events. This is
+ // based on the assumption that most traces that have ftrace either:
+ // - Are proto traces captured via perfetto, in which case traced_probes
+ // emits ftrace per-cpu stats that end up in the stats table.
+ // - Have a raw event with non-zero cpu or utid.
+ // Notes:
+ // - The "+1 > 1" is to avoid pushing down the constraints to the "raw"
+ // table, which would compute a full column filter without being aware
+ // of the limit 1, and instead delegate the filtering to the iterator.
+ const query = `select '_' as _ from raw
+ where cpu + 1 > 1 or utid + 1 > 1 limit 1`;
const result = await assertExists(this.engine).query(query);
- const hasFtrace = !!slowlyCountRows(result);
- globals.publish('HasFtrace', hasFtrace);
+ const hasFtrace = result.numRows() > 0;
+ publishHasFtrace(hasFtrace);
}
+ globals.dispatch(Actions.removeDebugTrack({}));
globals.dispatch(Actions.sortThreadTracks({}));
+
await this.selectFirstHeapProfile();
+ if (PERF_SAMPLE_FLAG.get()) {
+ await this.selectPerfSample();
+ }
return engineMode;
}
+ private async selectPerfSample() {
+ const query = `select ts, upid
+ from perf_sample
+ join thread using (utid)
+ order by ts desc limit 1`;
+ const profile = await assertExists(this.engine).query(query);
+ if (profile.numRows() !== 1) return;
+ const row = profile.firstRow({ts: NUM, upid: NUM});
+ const ts = row.ts;
+ const upid = row.upid;
+ globals.dispatch(
+ Actions.selectPerfSamples({id: 0, upid, ts, type: 'perf'}));
+ }
+
private async selectFirstHeapProfile() {
const query = `select * from
(select distinct(ts) as ts, 'native' as type,
@@ -345,10 +434,11 @@
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];
+ if (profile.numRows() !== 1) return;
+ const row = profile.firstRow({ts: NUM, type: STR, upid: NUM});
+ const ts = row.ts;
+ const type = row.type;
+ const upid = row.upid;
globals.dispatch(Actions.selectHeapProfile({id: 0, upid, ts, type}));
}
@@ -361,26 +451,38 @@
private async listThreads() {
this.updateStatus('Reading thread list');
- const sqlQuery = `select utid, tid, pid, thread.name,
+ const query = `select
+ utid,
+ tid,
+ pid,
+ ifnull(thread.name, '') as threadName,
ifnull(
case when length(process.name) > 0 then process.name else null end,
- thread.name),
- process.cmdline
+ thread.name) as procName,
+ process.cmdline as cmdline
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 result = await assertExists(this.engine).query(query);
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];
- const threadName = threadRows.columns[3].stringValues![i];
- const procName = threadRows.columns[4].stringValues![i];
- const cmdline = threadRows.columns[5].stringValues![i];
+ const it = result.iter({
+ utid: NUM,
+ tid: NUM,
+ pid: NUM_NULL,
+ threadName: STR,
+ procName: STR_NULL,
+ cmdline: STR_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const utid = it.utid;
+ const tid = it.tid;
+ const pid = it.pid === null ? undefined : it.pid;
+ const threadName = it.threadName;
+ const procName = it.procName === null ? undefined : it.procName;
+ const cmdline = it.cmdline === null ? undefined : it.cmdline;
threads.push({utid, tid, threadName, pid, procName, cmdline});
- } // for (record ...)
- globals.publish('Threads', threads);
+ }
+ publishThreads(threads);
}
private async loadTimelineOverview(traceTime: TimeSpan) {
@@ -398,19 +500,20 @@
const endNs = toNsCeil(endSec);
// Sched overview.
- const schedRows = await engine.query(
- `select sum(dur)/${stepSec}/1e9, cpu from sched ` +
+ const schedResult = await engine.query(
+ `select sum(dur)/${stepSec}/1e9 as load, cpu from sched ` +
`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++) {
- const load = schedRows.columns[0].doubleValues![i];
- const cpu = schedRows.columns[1].longValues![i];
+ const it = schedResult.iter({load: NUM, cpu: NUM});
+ for (; it.valid(); it.next()) {
+ const load = it.load;
+ const cpu = it.cpu;
schedData[cpu] = {startSec, endSec, load};
hasSchedOverview = true;
- } // for (record ...)
- globals.publish('OverviewData', schedData);
- } // for (step ...)
+ }
+ publishOverviewData(schedData);
+ }
if (hasSchedOverview) {
return;
@@ -419,27 +522,30 @@
// Slices overview.
const traceStartNs = toNs(traceTime.start);
const stepSecNs = toNs(stepSec);
- const sliceSummaryQuery = await engine.query(`select
+ const sliceResult = await engine.query(`select
bucket,
upid,
- sum(utid_sum) / cast(${stepSecNs} as float) as upid_sum
+ sum(utid_sum) / cast(${stepSecNs} as float) as load
from thread
inner join (
select
- cast((ts - ${traceStartNs})/${stepSecNs} as int) as bucket,
+ ifnull(cast((ts - ${traceStartNs})/${
+ stepSecNs} as int), 0) as bucket,
sum(dur) as utid_sum,
utid
from slice
inner join thread_track on slice.track_id = thread_track.id
group by bucket, utid
) using(utid)
+ where upid is not null
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];
- const load = sliceSummaryQuery.columns[2].doubleValues![i];
+ const it = sliceResult.iter({bucket: NUM, upid: NUM, load: NUM});
+ for (; it.valid(); it.next()) {
+ const bucket = it.bucket;
+ const upid = it.upid;
+ const load = it.load;
const startSec = traceTime.start + stepSec * bucket;
const endSec = startSec + stepSec;
@@ -451,7 +557,26 @@
}
loadArray.push({startSec, endSec, load});
}
- globals.publish('OverviewData', slicesData);
+ publishOverviewData(slicesData);
+ }
+
+ private async cacheCurrentTrace(): Promise<string> {
+ const engine = assertExists(this.engine);
+ const result = await engine.query(`select str_value as uuid from metadata
+ where name = 'trace_uuid'`);
+ if (result.numRows() === 0) {
+ throw new Error('metadata.trace_uuid could not be found.');
+ }
+ const traceUuid = result.firstRow({uuid: STR}).uuid;
+ const engineConfig = assertExists(globals.state.engines[engine.id]);
+ if (!cacheTrace(engineConfig.source, traceUuid)) {
+ // If the trace is not cacheable (has been opened from URL or RPC) don't
+ // append a ?trace_id to the URL. Doing so would cause an error if the
+ // tab is discarded or the user hits the reload button because the trace
+ // is not in the cache.
+ return '';
+ }
+ return traceUuid;
}
async initialiseHelperViews() {
@@ -504,15 +629,13 @@
);
`);
- 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']) {
+
+ for (const [flag, metric] of FLAGGED_METRICS) {
+ if (!flag.get()) {
+ continue;
+ }
+
+
this.updateStatus(`Computing ${metric} metric`);
try {
// We don't care about the actual result of metric here as we are just
@@ -520,7 +643,7 @@
await engine.computeMetric([metric]);
} catch (e) {
if (e instanceof QueryError) {
- globals.publish('MetricError', 'MetricError: ' + e.message);
+ publishMetricError('MetricError: ' + e.message);
continue;
} else {
throw e;
@@ -534,8 +657,9 @@
let hasDur = false;
let hasUpid = false;
let hasValue = false;
- for (let i = 0; i < slowlyCountRows(result); i++) {
- const name = result.columns[1].stringValues![i];
+ const it = result.iter({name: STR});
+ for (; it.valid(); it.next()) {
+ const name = it.name;
hasSliceName = hasSliceName || name === 'slice_name';
hasDur = hasDur || name === 'dur';
hasUpid = hasUpid || name === 'upid';
@@ -572,39 +696,40 @@
if (hasValue) {
const minMax = await engine.query(`
- SELECT MIN(value) as min_value, MAX(value) as max_value
- FROM ${metric}_event
- WHERE ${upidColumnWhere} != 0`);
- const min = minMax.columns[0].longValues![0];
- const max = minMax.columns[1].longValues![0];
+ SELECT
+ IFNULL(MIN(value), 0) as minValue,
+ IFNULL(MAX(value), 0) as maxValue
+ FROM ${metric}_event
+ WHERE ${upidColumnWhere} != 0`);
+ const row = minMax.firstRow({minValue: NUM, maxValue: NUM});
await engine.query(`
- INSERT INTO annotation_counter_track(
- name, __metric_name, min_value, max_value, upid)
- SELECT DISTINCT
- track_name,
- '${metric}' as metric_name,
- CASE ${upidColumnWhere} WHEN 0 THEN NULL ELSE ${min} END,
- CASE ${upidColumnWhere} WHEN 0 THEN NULL ELSE ${max} END,
- ${upidColumnSelect}
- FROM ${metric}_event
- WHERE track_type = 'counter'
- `);
+ INSERT INTO annotation_counter_track(
+ name, __metric_name, min_value, max_value, upid)
+ SELECT DISTINCT
+ track_name,
+ '${metric}' as metric_name,
+ CASE ${upidColumnWhere} WHEN 0 THEN NULL ELSE ${row.minValue} END,
+ CASE ${upidColumnWhere} WHEN 0 THEN NULL ELSE ${row.maxValue} END,
+ ${upidColumnSelect}
+ FROM ${metric}_event
+ WHERE track_type = 'counter'
+ `);
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
- JOIN annotation_counter_track t
- ON a.track_name = t.name AND t.__metric_name = '${metric}'
- ORDER BY t.id, ts
- `);
+ INSERT INTO annotation_counter(id, track_id, ts, value)
+ SELECT
+ -1 as id,
+ t.id AS track_id,
+ ts,
+ value
+ FROM ${metric}_event 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);
+ publishMetricError('MetricError: ' + e.message);
} else {
throw e;
}
@@ -619,5 +744,3 @@
}));
}
}
-
-
diff --git a/ui/src/controller/trace_converter.ts b/ui/src/controller/trace_converter.ts
deleted file mode 100644
index f839100..0000000
--- a/ui/src/controller/trace_converter.ts
+++ /dev/null
@@ -1,179 +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 {defer} from '../base/deferred';
-import {assertExists} from '../base/logging';
-import {Actions} from '../common/actions';
-import {ConversionJobStatus} from '../common/conversion_jobs';
-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 jobName = 'open_in_legacy';
- globals.publish('ConversionJobStatusUpdate', {
- jobName,
- jobStatus: ConversionJobStatus.InProgress,
- });
- 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);
- })
- .finally(() => {
- globals.publish('ConversionJobStatusUpdate', {
- jobName,
- jobStatus: ConversionJobStatus.NotRunning,
- });
- });
-}
-
-export function ConvertTraceAndDownload(
- trace: Blob, format: Format, truncate?: 'start'|'end') {
- const jobName = `convert_${format}`;
- globals.publish('ConversionJobStatusUpdate', {
- jobName,
- jobStatus: ConversionJobStatus.InProgress,
- });
- 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;
- downloadFile(fsNodeToBlob(fsNode), `trace.${format}`);
- module.FS.unlink(outPath);
- })
- .finally(() => {
- globals.publish('ConversionJobStatusUpdate', {
- jobName,
- jobStatus: ConversionJobStatus.NotRunning,
- });
- });
-}
-
-export function ConvertTraceToPprof(
- pid: number, src: TraceSource, ts1: number, ts2?: number) {
- const jobName = 'convert_pprof';
- globals.publish('ConversionJobStatusUpdate', {
- jobName,
- jobStatus: ConversionJobStatus.InProgress,
- });
- 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 fileNode =
- module.FS.lookupPath(`/tmp/${heapDirName}/${heapDump}`).node;
- fileNum++;
- const fileName = `/heap_dump.${fileNum}.${pid}.pb`;
- downloadFile(fsNodeToBlob(fileNode), fileName);
- });
- });
- })
- .finally(() => {
- globals.publish('ConversionJobStatusUpdate', {
- jobName,
- jobStatus: ConversionJobStatus.NotRunning,
- });
- });
-}
-
-async function runTraceconv(trace: Blob, args: string[]) {
- const deferredRuntimeInitialized = defer<void>();
- const module = trace_to_text({
- noInitialRun: true,
- locateFile: (s: string) => s,
- print: updateStatus,
- printErr: updateStatus,
- onRuntimeInitialized: () => deferredRuntimeInitialized.resolve()
- });
- await deferredRuntimeInitialized;
- module.FS.mkdir('/fs');
- module.FS.mount(
- assertExists(module.FS.filesystems.WORKERFS),
- {blobs: [{name: 'trace.proto', data: trace}]},
- '/fs');
- updateStatus('Converting trace');
- module.callMain(args);
- updateStatus('Trace conversion completed');
- return module;
-}
-
-async function generateBlob(src: TraceSource) {
- let blob: Blob = new Blob();
- if (src.type === 'URL') {
- const resp = await fetch(src.url);
- if (resp.status !== 200) {
- throw new Error(`fetch() failed with HTTP error ${resp.status}`);
- }
- blob = await resp.blob();
- } else if (src.type === 'ARRAY_BUFFER') {
- blob = new Blob([new Uint8Array(src.buffer, 0, src.buffer.byteLength)]);
- } else if (src.type === 'FILE') {
- blob = src.file;
- } else {
- throw new Error(`Conversion not supported for ${JSON.stringify(src)}`);
- }
- return blob;
-}
-
-function fsNodeToBlob(fsNode: trace_to_text.FileSystemNode): Blob {
- const fileSize = assertExists(fsNode.usedBytes);
- const bufView = new Uint8Array(fsNode.contents.buffer, 0, fileSize);
- return new Blob([bufView]);
-}
-
-function downloadFile(file: Blob, name: string) {
- globals.publish('FileDownload', {file, name});
-}
-
-function updateStatus(msg: {}) {
- console.log(msg);
- globals.dispatch(Actions.updateStatus({
- msg: msg.toString(),
- timestamp: Date.now() / 1000,
- }));
-}
diff --git a/ui/src/controller/trace_error_controller.ts b/ui/src/controller/trace_error_controller.ts
index a8bb80b..6b6f461 100644
--- a/ui/src/controller/trace_error_controller.ts
+++ b/ui/src/controller/trace_error_controller.ts
@@ -13,9 +13,10 @@
// limitations under the License.
import {Engine} from '../common/engine';
+import {NUM} from '../common/query_result';
+import {publishTraceErrors} from '../frontend/publish';
import {Controller} from './controller';
-import {globals} from './globals';
export interface TraceErrorControllerArgs {
engine: Engine;
@@ -32,10 +33,13 @@
return;
}
this.hasRun = true;
- this.args.engine
- .queryOneRow(`SELECT sum(value) FROM stats WHERE severity != 'info'`)
+ const engine = this.args.engine;
+ engine
+ .query(
+ `SELECT sum(value) as sumValue FROM stats WHERE severity != 'info'`)
.then(result => {
- globals.publish('TraceErrors', result[0]);
+ const errors = result.firstRow({sumValue: NUM}).sumValue;
+ publishTraceErrors(errors);
});
}
}
diff --git a/ui/src/controller/trace_stream.ts b/ui/src/controller/trace_stream.ts
index 34c3861..f6c9da6 100644
--- a/ui/src/controller/trace_stream.ts
+++ b/ui/src/controller/trace_stream.ts
@@ -100,7 +100,7 @@
private bytesRead = 0;
private bytesTotal = 0;
private uri: string;
- private httpStream?: ReadableStreamReader;
+ private httpStream?: ReadableStreamReader<Uint8Array>;
constructor(uri: string) {
assertTrue(uri.startsWith('http://') || uri.startsWith('https://'));
@@ -116,8 +116,7 @@
}
const len = response.headers.get('Content-Length');
this.bytesTotal = len ? Number.parseInt(len, 10) : 0;
- // tslint:disable-next-line no-any
- this.httpStream = (response.body as any).getReader();
+ this.httpStream = response.body!.getReader();
}
let eof = false;
@@ -128,8 +127,7 @@
// 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};
+ const res = await this.httpStream.read();
if (res.value) {
chunks.push(res.value);
bytesRead += res.value.length;
diff --git a/ui/src/controller/track_controller.ts b/ui/src/controller/track_controller.ts
index b2a82fb..fd6aae6 100644
--- a/ui/src/controller/track_controller.ts
+++ b/ui/src/controller/track_controller.ts
@@ -18,6 +18,7 @@
import {TraceTime, TrackState} from '../common/state';
import {fromNs, toNs} from '../common/time';
import {LIMIT, TrackData} from '../common/track_data';
+import {publishTrackData} from '../frontend/publish';
import {Controller} from './controller';
import {ControllerFactory} from './controller';
@@ -68,7 +69,7 @@
// Must be overridden by the track implementation. Is invoked when the track
// frontend runs out of cached data. The derived track controller is expected
// to publish new track data in response to this call.
- abstract async onBoundsChange(start: number, end: number, resolution: number):
+ abstract onBoundsChange(start: number, end: number, resolution: number):
Promise<Data>;
get trackState(): TrackState {
@@ -93,7 +94,7 @@
publish(data: Data): void {
this.data = data;
- globals.publish('TrackData', {id: this.trackId, data});
+ publishTrackData({id: this.trackId, data});
}
/**
@@ -118,11 +119,6 @@
return result;
}
- protected async queryV2(query: string) {
- const result = await this.engine.queryV2(query);
- return result;
- }
-
private shouldReload(): boolean {
const {lastTrackReloadRequest} = globals.state;
return !!lastTrackReloadRequest &&
diff --git a/ui/src/controller/track_decider.ts b/ui/src/controller/track_decider.ts
index 9db1325..eb7f9de 100644
--- a/ui/src/controller/track_decider.ts
+++ b/ui/src/controller/track_decider.ts
@@ -13,22 +13,21 @@
// limitations under the License.
import * as uuidv4 from 'uuid/v4';
-import {assertExists} from '../base/logging';
+import {assertExists} from '../base/logging';
import {
Actions,
AddTrackArgs,
DeferredAction,
} from '../common/actions';
import {Engine} from '../common/engine';
+import {PERF_SAMPLE_FLAG} from '../common/feature_flags';
import {
- iter,
NUM,
NUM_NULL,
- slowlyCountRows,
STR,
STR_NULL,
-} from '../common/query_iterator';
+} from '../common/query_result';
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';
@@ -43,6 +42,9 @@
} from '../tracks/expected_frames/common';
import {HEAP_PROFILE_TRACK_KIND} from '../tracks/heap_profile/common';
import {
+ PERF_SAMPLES_PROFILE_TRACK_KIND
+} from '../tracks/perf_samples_profile/common';
+import {
PROCESS_SCHEDULING_TRACK_KIND
} from '../tracks/process_scheduling/common';
import {PROCESS_SUMMARY_TRACK} from '../tracks/process_summary/common';
@@ -149,39 +151,41 @@
async addCpuFreqTracks(): Promise<void> {
const cpus = await this.engine.getCpus();
- const maxCpuFreq = await this.engine.query(`
- select max(value)
+ const maxCpuFreqResult = await this.engine.query(`
+ select ifnull(max(value), 0) as freq
from counter c
inner join cpu_counter_track t on c.track_id = t.id
where name = 'cpufreq';
`);
+ const maxCpuFreq = maxCpuFreqResult.firstRow({freq: NUM}).freq;
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(`
+ const cpuFreqIdleResult = await this.engine.query(`
select
- id as cpu_freq_id,
+ id as cpuFreqId,
(
select id
from cpu_counter_track
where name = 'cpuidle'
and cpu = ${cpu}
limit 1
- ) as cpu_idle_id
+ ) as cpuIdleId
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;
+ if (cpuFreqIdleResult.numRows() > 0) {
+ const row = cpuFreqIdleResult.firstRow({
+ cpuFreqId: NUM,
+ cpuIdleId: NUM_NULL,
+ });
+ const freqTrackId = row.cpuFreqId;
+ const idleTrackId = row.cpuIdleId === null ? undefined : row.cpuIdleId;
this.tracksToAdd.push({
engineId: this.engineId,
@@ -191,7 +195,7 @@
trackGroup: SCROLLING_TRACK_GROUP,
config: {
cpu,
- maximumValue: +maxCpuFreq.columns[0].doubleValues![0],
+ maximumValue: maxCpuFreq,
freqTrackId,
idleTrackId,
}
@@ -203,25 +207,30 @@
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
+ t.name as name,
+ t.track_ids as trackIds,
+ MAX(experimental_slice_layout.layout_depth) as maxDepth
FROM (
SELECT name, GROUP_CONCAT(track.id) AS track_ids
FROM track
- WHERE track.type = "track"
+ WHERE track.type = "track" or track.type = "gpu_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;
+ GROUP BY t.track_ids
+ ORDER BY t.name;
`);
- 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 it = rawGlobalAsyncTracks.iter({
+ name: STR_NULL,
+ trackIds: STR,
+ maxDepth: NUM,
+ });
+
+ for (; it.valid(); it.next()) {
+ const name = it.name === null ? undefined : it.name;
+ const rawTrackIds = it.trackIds;
const trackIds = rawTrackIds.split(',').map(v => Number(v));
- const maxDepth = +rawGlobalAsyncTracks.columns[2].longValues![i];
+ const maxDepth = it.maxDepth;
const kind = ASYNC_SLICE_TRACK_KIND;
const track = {
engineId: this.engineId,
@@ -240,23 +249,26 @@
async addGpuFreqTracks(): Promise<void> {
const numGpus = await this.engine.getNumberOfGpus();
- const maxGpuFreq = await this.engine.query(`
- select max(value)
+ const maxGpuFreqResult = await this.engine.query(`
+ select ifnull(max(value), 0) as maximumValue
from counter c
inner join gpu_counter_track t on c.track_id = t.id
where name = 'gpufreq';
`);
+ const maximumValue =
+ maxGpuFreqResult.firstRow({maximumValue: NUM}).maximumValue;
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(`
+ const freqExistsResult = await this.engine.query(`
select id
from gpu_counter_track
where name = 'gpufreq' and gpu_id = ${gpu}
limit 1;
`);
- if (slowlyCountRows(freqExists) > 0) {
+ if (freqExistsResult.numRows() > 0) {
+ const trackId = freqExistsResult.firstRow({id: NUM}).id;
this.tracksToAdd.push({
engineId: this.engineId,
kind: COUNTER_TRACK_KIND,
@@ -264,8 +276,8 @@
trackKindPriority: TrackKindPriority.ORDINARY,
trackGroup: SCROLLING_TRACK_GROUP,
config: {
- trackId: +freqExists.columns[0].longValues![0],
- maximumValue: +maxGpuFreq.columns[0].doubleValues![0],
+ trackId,
+ maximumValue,
}
});
}
@@ -276,16 +288,61 @@
// 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'
+ from (
+ select name, id
+ from counter_track
+ where type = 'counter_track'
+ union
+ select name, id
+ from gpu_counter_track
+ where name != 'gpufreq'
+ )
+ order by name
`);
- for (let i = 0; i < slowlyCountRows(globalCounters); i++) {
- const name = globalCounters.columns[0].stringValues![i];
- const trackId = +globalCounters.columns[1].longValues![i];
+
+ const it = globalCounters.iter({
+ name: STR,
+ id: NUM,
+ });
+
+ for (; it.valid(); it.next()) {
+ const name = it.name;
+ const trackId = it.id;
+ this.tracksToAdd.push({
+ engineId: this.engineId,
+ kind: COUNTER_TRACK_KIND,
+ name,
+ trackKindPriority: TrackDecider.inferTrackKindPriority(name),
+ trackGroup: SCROLLING_TRACK_GROUP,
+ config: {
+ name,
+ trackId,
+ }
+ });
+ }
+ }
+
+ async addCpuPerfCounterTracks(): Promise<void> {
+ // Perf counter tracks are bound to CPUs, follow the scheduling and
+ // frequency track naming convention ("Cpu N ...").
+ // Note: we might not have a track for a given cpu if no data was seen from
+ // it. This might look surprising in the UI, but placeholder tracks are
+ // wasteful as there's no way of collapsing global counter tracks at the
+ // moment.
+ const result = await this.engine.query(`
+ select printf("Cpu %u %s", cpu, name) as name, id
+ from perf_counter_track as pct
+ order by perf_session_id asc, pct.name asc, cpu asc
+ `);
+
+ const it = result.iter({
+ name: STR,
+ id: NUM,
+ });
+
+ for (; it.valid(); it.next()) {
+ const name = it.name;
+ const trackId = it.id;
this.tracksToAdd.push({
engineId: this.engineId,
kind: COUNTER_TRACK_KIND,
@@ -345,9 +402,11 @@
}
async addLogsTrack(): Promise<void> {
- const logCount =
- await this.engine.query(`select count(1) from android_logs`);
- if (logCount.columns[0].longValues![0] > 0) {
+ const result =
+ await this.engine.query(`select count(1) as cnt from android_logs`);
+ const count = result.firstRow({cnt: NUM}).cnt;
+
+ if (count > 0) {
this.tracksToAdd.push({
engineId: this.engineId,
kind: ANDROID_LOGS_TRACK_KIND,
@@ -360,12 +419,19 @@
}
async addAnnotationTracks(): Promise<void> {
- const annotationSliceRows = await this.engine.query(`
+ const sliceResult = 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];
+
+ const sliceIt = sliceResult.iter({
+ id: NUM,
+ name: STR,
+ upid: NUM,
+ });
+
+ for (; sliceIt.valid(); sliceIt.next()) {
+ const id = sliceIt.id;
+ const name = sliceIt.name;
+ const upid = sliceIt.upid;
this.tracksToAdd.push({
engineId: this.engineId,
kind: SLICE_TRACK_KIND,
@@ -381,19 +447,31 @@
});
}
- const annotationCounterRows = await this.engine.query(`
- SELECT id, name, upid, min_value, max_value
+ const counterResult = await this.engine.query(`
+ SELECT
+ id,
+ name,
+ upid,
+ min_value as minValue,
+ max_value as maxValue
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];
+
+ const counterIt = counterResult.iter({
+ id: NUM,
+ name: STR,
+ upid: NUM,
+ minValue: NUM_NULL,
+ maxValue: NUM_NULL,
+ });
+
+ for (; counterIt.valid(); counterIt.next()) {
+ const id = counterIt.id;
+ const name = counterIt.name;
+ const upid = counterIt.upid;
+ const minimumValue =
+ counterIt.minValue === null ? undefined : counterIt.minValue;
+ const maximumValue =
+ counterIt.maxValue === null ? undefined : counterIt.maxValue;
this.tracksToAdd.push({
engineId: this.engineId,
kind: 'CounterTrack',
@@ -413,7 +491,7 @@
}
async addThreadStateTracks(): Promise<void> {
- const query = await this.engine.query(`
+ const result = await this.engine.query(`
select
utid,
tid,
@@ -427,22 +505,19 @@
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 it = result.iter({
+ utid: NUM,
+ upid: NUM_NULL,
+ tid: NUM_NULL,
+ pid: NUM_NULL,
+ threadName: STR_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const utid = it.utid;
+ const tid = it.tid;
+ const upid = it.upid;
+ const pid = it.pid;
+ const threadName = it.threadName;
const uuid = this.getUuidUnchecked(utid, upid);
if (uuid === undefined) {
// If a thread has no scheduling activity (i.e. the sched table has zero
@@ -464,7 +539,7 @@
}
async addThreadCpuSampleTracks(): Promise<void> {
- const query = await this.engine.query(`
+ const result = await this.engine.query(`
select
utid,
tid,
@@ -479,19 +554,16 @@
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 it = result.iter({
+ utid: NUM,
+ upid: NUM_NULL,
+ tid: NUM_NULL,
+ threadName: STR_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const utid = it.utid;
+ const upid = it.upid;
+ const threadName = it.threadName;
const uuid = this.getUuid(utid, upid);
this.tracksToAdd.push({
engineId: this.engineId,
@@ -506,7 +578,7 @@
}
async addThreadCounterTracks(): Promise<void> {
- const query = await this.engine.query(`
+ const result = await this.engine.query(`
select
thread_counter_track.name as trackName,
utid,
@@ -522,29 +594,26 @@
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 it = result.iter({
+ trackName: STR_NULL,
+ utid: NUM,
+ upid: NUM_NULL,
+ tid: NUM_NULL,
+ threadName: STR_NULL,
+ startTs: NUM_NULL,
+ trackId: NUM,
+ endTs: NUM_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const utid = it.utid;
+ const tid = it.tid;
+ const upid = it.upid;
+ const trackId = it.trackId;
+ const trackName = it.trackName;
+ const threadName = it.threadName;
const uuid = this.getUuid(utid, upid);
- const startTs = row.startTs === null ? undefined : row.startTs;
- const endTs = row.endTs === null ? undefined : row.endTs;
+ const startTs = it.startTs === null ? undefined : it.startTs;
+ const endTs = it.endTs === null ? undefined : it.endTs;
const kind = COUNTER_TRACK_KIND;
const name = TrackDecider.getTrackName(
{name: trackName, utid, tid, kind, threadName, threadTrack: true});
@@ -560,7 +629,7 @@
}
async addProcessAsyncSliceTracks(): Promise<void> {
- const query = await this.engine.query(`
+ const result = await this.engine.query(`
select
process_track.upid as upid,
process_track.name as trackName,
@@ -577,32 +646,29 @@
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 it = result.iter({
+ upid: NUM,
+ trackName: STR_NULL,
+ trackIds: STR,
+ processName: STR_NULL,
+ pid: NUM_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const upid = it.upid;
+ const trackName = it.trackName;
+ const rawTrackIds = it.trackIds;
const trackIds = rawTrackIds.split(',').map(v => Number(v));
- const processName = row.processName;
- const pid = row.pid;
+ const processName = it.processName;
+ const pid = it.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
+ SELECT IFNULL(MAX(layout_depth), 0) as depth
FROM experimental_slice_layout('${rawTrackIds}');
`);
- const maxDepth = +depthResult.columns[0].longValues![0];
+ const maxDepth = depthResult.firstRow({depth: NUM}).depth;
const kind = ASYNC_SLICE_TRACK_KIND;
const name = TrackDecider.getTrackName(
@@ -622,7 +688,7 @@
}
async addActualFramesTracks(): Promise<void> {
- const query = await this.engine.query(`
+ const result = await this.engine.query(`
select
upid,
trackName,
@@ -642,32 +708,29 @@
) 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 it = result.iter({
+ upid: NUM,
+ trackName: STR_NULL,
+ trackIds: STR,
+ processName: STR_NULL,
+ pid: NUM_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const upid = it.upid;
+ const trackName = it.trackName;
+ const rawTrackIds = it.trackIds;
const trackIds = rawTrackIds.split(',').map(v => Number(v));
- const processName = row.processName;
- const pid = row.pid;
+ const processName = it.processName;
+ const pid = it.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
+ SELECT IFNULL(MAX(layout_depth), 0) as depth
FROM experimental_slice_layout('${rawTrackIds}');
`);
- const maxDepth = +depthResult.columns[0].longValues![0];
+ const maxDepth = depthResult.firstRow({depth: NUM}).depth;
const kind = ACTUAL_FRAMES_SLICE_TRACK_KIND;
const name = TrackDecider.getTrackName(
@@ -687,7 +750,7 @@
}
async addExpectedFramesTracks(): Promise<void> {
- const query = await this.engine.query(`
+ const result = await this.engine.query(`
select
upid,
trackName,
@@ -707,32 +770,30 @@
) 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 it = result.iter({
+ upid: NUM,
+ trackName: STR_NULL,
+ trackIds: STR,
+ processName: STR_NULL,
+ pid: NUM_NULL,
+ });
+
+ for (; it.valid(); it.next()) {
+ const upid = it.upid;
+ const trackName = it.trackName;
+ const rawTrackIds = it.trackIds;
const trackIds = rawTrackIds.split(',').map(v => Number(v));
- const processName = row.processName;
- const pid = row.pid;
+ const processName = it.processName;
+ const pid = it.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
+ SELECT IFNULL(MAX(layout_depth), 0) as depth
FROM experimental_slice_layout('${rawTrackIds}');
`);
- const maxDepth = +depthResult.columns[0].longValues![0];
+ const maxDepth = depthResult.firstRow({depth: NUM}).depth;
const kind = EXPECTED_FRAMES_SLICE_TRACK_KIND;
const name = TrackDecider.getTrackName(
@@ -752,45 +813,46 @@
}
async addThreadSliceTracks(): Promise<void> {
- const query = await this.engine.query(`
+ const result = 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,
+ max(slice.depth) as maxDepth,
+ (count(thread_slice.id) = count(slice.id)) as onlyThreadSlice,
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)
+ left join thread_slice on slice.id = thread_slice.id
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 it = result.iter({
+ utid: NUM,
+ trackId: NUM,
+ trackName: STR_NULL,
+ tid: NUM_NULL,
+ threadName: STR_NULL,
+ maxDepth: NUM,
+ upid: NUM_NULL,
+ pid: NUM_NULL,
+ onlyThreadSlice: NUM,
+ });
+ for (; it.valid(); it.next()) {
+ const utid = it.utid;
+ const trackId = it.trackId;
+ const trackName = it.trackName;
+ const tid = it.tid;
+ const threadName = it.threadName;
+ const upid = it.upid;
+ const pid = it.pid;
+ const maxDepth = it.maxDepth;
+ const onlyThreadSlice = it.onlyThreadSlice;
const trackKindPriority =
TrackDecider.inferTrackKindPriority(threadName, tid, pid);
@@ -805,13 +867,13 @@
name,
trackGroup: uuid,
trackKindPriority,
- config: {trackId, maxDepth, tid}
+ config: {trackId, maxDepth, tid, isThreadSlice: onlyThreadSlice === 1}
});
}
}
async addProcessCounterTracks(): Promise<void> {
- const query = await this.engine.query(`
+ const result = await this.engine.query(`
select
process_counter_track.id as trackId,
process_counter_track.name as trackName,
@@ -823,27 +885,24 @@
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);
+ const it = result.iter({
+ trackId: NUM,
+ trackName: STR_NULL,
+ upid: NUM,
+ pid: NUM_NULL,
+ processName: STR_NULL,
+ startTs: NUM_NULL,
+ endTs: NUM_NULL,
+ });
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 pid = it.pid;
+ const upid = it.upid;
+ const trackId = it.trackId;
+ const trackName = it.trackName;
+ const processName = it.processName;
const uuid = this.getUuid(0, upid);
- const startTs = row.startTs === null ? undefined : row.startTs;
- const endTs = row.endTs === null ? undefined : row.endTs;
+ const startTs = it.startTs === null ? undefined : it.startTs;
+ const endTs = it.endTs === null ? undefined : it.endTs;
const kind = COUNTER_TRACK_KIND;
const name = TrackDecider.getTrackName(
{name: trackName, upid, pid, kind, processName});
@@ -864,14 +923,13 @@
}
async addProcessHeapProfileTracks(): Promise<void> {
- const query = await this.engine.query(`
+ const result = 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;
+ for (const it = result.iter({upid: NUM}); it.valid(); it.next()) {
+ const upid = it.upid;
const uuid = this.getUuid(0, upid);
this.tracksToAdd.push({
engineId: this.engineId,
@@ -884,6 +942,26 @@
}
}
+ async addProcessPerfSamplesTracks(): Promise<void> {
+ const result = await this.engine.query(`
+ select distinct(process.upid) from process
+ join thread on process.upid = thread.upid
+ join perf_sample on thread.utid = perf_sample.utid
+ `);
+ for (const it = result.iter({upid: NUM}); it.valid(); it.next()) {
+ const upid = it.upid;
+ const uuid = this.getUuid(0, upid);
+ this.tracksToAdd.push({
+ engineId: this.engineId,
+ kind: PERF_SAMPLES_PROFILE_TRACK_KIND,
+ trackKindPriority: TrackKindPriority.ORDINARY,
+ name: `Perf Samples`,
+ trackGroup: uuid,
+ config: {upid}
+ });
+ }
+ }
+
getUuidUnchecked(utid: number, upid: number|null) {
return upid === null ? this.utidToUuid.get(utid) :
this.upidToUuid.get(upid);
@@ -916,7 +994,7 @@
// total cpu time *for the whole parent process*
// upid
// utid
- const query = await this.engine.query(`
+ const result = await this.engine.query(`
select
the_tracks.upid,
the_tracks.utid,
@@ -949,7 +1027,7 @@
from sched join thread using(utid)
group by upid
) using(upid)
- left join (select upid, sum(value) as total_cycles
+ left join (select upid, max(value) as total_cycles
from android_thread_time_in_state_event
group by upid
) using(upid)
@@ -974,28 +1052,25 @@
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;
+ const it = result.iter({
+ utid: NUM,
+ upid: NUM_NULL,
+ tid: NUM_NULL,
+ pid: NUM_NULL,
+ threadName: STR_NULL,
+ processName: STR_NULL,
+ hasSched: NUM_NULL,
+ hasHeapProfiles: NUM_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const utid = it.utid;
+ const tid = it.tid;
+ const upid = it.upid;
+ const pid = it.pid;
+ const threadName = it.threadName;
+ const processName = it.processName;
+ const hasSched = !!it.hasSched;
+ const hasHeapProfiles = !!it.hasHeapProfiles;
// Group by upid if present else by utid.
let pUuid =
@@ -1040,6 +1115,7 @@
await this.addGlobalAsyncTracks();
await this.addGpuFreqTracks();
await this.addGlobalCounterTracks();
+ await this.addCpuPerfCounterTracks();
await this.groupGlobalIonTracks();
// Create the per-process track groups. Note that this won't necessarily
@@ -1049,6 +1125,9 @@
await this.addProcessTrackGroups();
await this.addProcessHeapProfileTracks();
+ if (PERF_SAMPLE_FLAG.get()) {
+ await this.addProcessPerfSamplesTracks();
+ }
await this.addProcessCounterTracks();
await this.addProcessAsyncSliceTracks();
await this.addActualFramesTracks();
diff --git a/ui/src/controller/validate_config.ts b/ui/src/controller/validate_config.ts
index 015131f..b5838c8 100644
--- a/ui/src/controller/validate_config.ts
+++ b/ui/src/controller/validate_config.ts
@@ -12,46 +12,176 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {createEmptyRecordConfig, RecordConfig} from '../common/state';
+import {RecordConfig, RecordMode} from '../common/state';
-interface RecordConfigValidationResult {
- config: RecordConfig;
- errorMessage?: string;
+type Json = JsonObject|Json[]|null|number|boolean|string;
+
+export interface JsonObject {
+ [key: string]: Json;
}
-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];
+class ObjectValidator {
+ raw: JsonObject;
+
+ constructor(raw: JsonObject) {
+ this.raw = raw;
+ }
+
+ number(key: string, def = 0): number {
+ if (!(key in this.raw)) {
+ return def;
+ }
+
+ const val = this.raw[key];
+ if (typeof val === 'number') {
+ return val;
} 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);
+ return def;
}
}
- 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,
- };
+ string(key: string, def = ''): string {
+ if (!(key in this.raw)) {
+ return def;
+ }
+
+ const val = this.raw[key];
+ if (typeof val === 'string') {
+ return val;
+ } else {
+ return def;
+ }
}
- return {config: newConfig};
+
+ stringArray(key: string, def: string[] = []): string[] {
+ if (!(key in this.raw)) {
+ return def;
+ }
+
+ const val = this.raw[key];
+ if (Array.isArray(val)) {
+ for (let i = 0; i < val.length; i++) {
+ if (typeof val[i] !== 'string') {
+ return def;
+ }
+ }
+ return val as string[];
+ } else {
+ return def;
+ }
+ }
+
+ boolean(key: string, def = false): boolean {
+ if (!(key in this.raw)) {
+ return def;
+ }
+
+ const val = this.raw[key];
+ if (typeof val === 'boolean') {
+ return val;
+ } else {
+ return def;
+ }
+ }
+
+ recordMode(key: string, def: RecordMode): RecordMode {
+ if (!(key in this.raw)) {
+ return def;
+ }
+
+ const mode = this.raw[key];
+ if (typeof mode !== 'string') {
+ return def;
+ }
+
+ if (mode === 'STOP_WHEN_FULL') {
+ return mode;
+ } else if (mode === 'RING_BUFFER') {
+ return mode;
+ } else if (mode === 'LONG_TRACE') {
+ return mode;
+ } else {
+ return def;
+ }
+ }
+}
+
+export function validateRecordConfig(config: JsonObject): RecordConfig {
+ const v = new ObjectValidator(config);
+
+ return {
+ mode: v.recordMode('mode', 'STOP_WHEN_FULL'),
+ durationMs: v.number('durationMs', 10000.0),
+ maxFileSizeMb: v.number('maxFileSizeMb', 100),
+ fileWritePeriodMs: v.number('fileWritePeriodMs', 2500),
+ bufferSizeMb: v.number('bufferSizeMb', 64.0),
+
+ cpuSched: v.boolean('cpuSched'),
+ cpuFreq: v.boolean('cpuFreq'),
+ cpuSyscall: v.boolean('cpuSyscall'),
+
+ gpuFreq: v.boolean('gpuFreq'),
+ gpuMemTotal: v.boolean('gpuMemTotal'),
+
+ ftrace: v.boolean('ftrace'),
+ atrace: v.boolean('atrace'),
+ ftraceEvents: v.stringArray('ftraceEvents'),
+ ftraceExtraEvents: v.string('ftraceExtraEvents'),
+ atraceCats: v.stringArray('atraceCats'),
+ atraceApps: v.string('atraceApps'),
+ ftraceBufferSizeKb: v.number('ftraceBufferSizeKb', 2 * 1024),
+ ftraceDrainPeriodMs: v.number('ftraceDrainPerionMs', 250),
+ androidLogs: v.boolean('androidLogs'),
+ androidLogBuffers: v.stringArray('androidLogBuffers'),
+ androidFrameTimeline: v.boolean('androidFrameTimeline'),
+
+ cpuCoarse: v.boolean('cpuCoarse'),
+ cpuCoarsePollMs: v.number('cpuCoarsePollMs', 1000),
+
+ batteryDrain: v.boolean('batteryDrain'),
+ batteryDrainPollMs: v.number('batteryDrainPollMs', 1000),
+
+ boardSensors: v.boolean('boardSensors'),
+
+ memHiFreq: v.boolean('memHiFreq'),
+ meminfo: v.boolean('meminfo'),
+ meminfoPeriodMs: v.number('meminfoPeriodMs', 1000),
+ meminfoCounters: v.stringArray('meminfoCounters'),
+
+ vmstat: v.boolean('vmstat'),
+ vmstatPeriodMs: v.number('vmstatPeriodMs', 1000),
+ vmstatCounters: v.stringArray('vmstatCounters'),
+
+ heapProfiling: v.boolean('heapProfiling'),
+ hpSamplingIntervalBytes: v.number('hpSamplingIntervalBytes', 4096),
+ hpProcesses: v.string('hpProcesses'),
+ hpContinuousDumpsPhase: v.number('hpContinuousDumpsPhase'),
+ hpContinuousDumpsInterval: v.number('hpContinuousDumpsInterval'),
+ hpSharedMemoryBuffer: v.number('hpSharedMemoryBuffer', 8 * 1048576),
+ hpBlockClient: v.boolean('hpBlockClient', true),
+ hpAllHeaps: v.boolean('hpAllHeaps'),
+
+ javaHeapDump: v.boolean('javaHeapDump'),
+ jpProcesses: v.string('jpProcesses'),
+ jpContinuousDumpsPhase: v.number('jpContinuousDumpsPhase'),
+ jpContinuousDumpsInterval: v.number('jpContinuousDumpsInterval'),
+
+ memLmk: v.boolean('memLmk'),
+ procStats: v.boolean('procStats'),
+ procStatsPeriodMs: v.number('procStatsPeriodMs', 1000),
+
+ chromeCategoriesSelected: v.stringArray('chromeCategoriesSelected'),
+
+ chromeLogs: v.boolean('chromeLogs'),
+ taskScheduling: v.boolean('taskScheduling'),
+ ipcFlows: v.boolean('ipcFlows'),
+ jsExecution: v.boolean('jsExecution'),
+ webContentRendering: v.boolean('webContentRendering'),
+ uiRendering: v.boolean('uiRendering'),
+ inputEvents: v.boolean('inputEvents'),
+ navigationAndLoading: v.boolean('navigationAndLoading'),
+ chromeHighOverheadCategoriesSelected:
+ v.stringArray('chromeHighOverheadCategoriesSelected'),
+ symbolizeKsyms: v.boolean('symbolizeKsyms'),
+ };
}
diff --git a/ui/src/controller/validate_config_jsdomtest.ts b/ui/src/controller/validate_config_jsdomtest.ts
index 370d54a..6503941 100644
--- a/ui/src/controller/validate_config_jsdomtest.ts
+++ b/ui/src/controller/validate_config_jsdomtest.ts
@@ -12,89 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {createEmptyRecordConfig, RecordConfig} from '../common/state';
+import {RecordConfig} from '../common/state';
import {validateRecordConfig} from './validate_config';
-test('validateRecordConfig test valid keys config', () => {
- const config: RecordConfig = createEmptyRecordConfig();
- const validationResult = validateRecordConfig(config);
+test('validateRecordConfig does not keep invalid keys', () => {
+ const key = 'Invalid key';
+ const config: RecordConfig =
+ validateRecordConfig({[key]: 'Some random value'});
- expect('errorMessage' in validationResult).toEqual(false);
-
- for (const key of Object.keys(validationResult.config)) {
- expect(key in config).toEqual(true);
- }
+ expect((config as object).hasOwnProperty(key)).toEqual(false);
});
-test('validateRecordConfig test no key config', () => {
- const emptyRecord: RecordConfig = createEmptyRecordConfig();
- const validationResult = validateRecordConfig({});
+test('validateRecordConfig keeps provided values', () => {
+ const value = 31337;
+ const config: RecordConfig = validateRecordConfig({'durationMs': value});
- 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);
- }
+ expect(config.durationMs).toEqual(value);
});
diff --git a/ui/src/frontend/analytics.ts b/ui/src/frontend/analytics.ts
index 076ed48..a16c624 100644
--- a/ui/src/frontend/analytics.ts
+++ b/ui/src/frontend/analytics.ts
@@ -12,18 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {getCurrentChannel} from '../common/channels';
import {globals} from '../frontend/globals';
import * as version from '../gen/perfetto_version';
+import {Router} from './router';
+
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')) {
+ // Only initialize logging on the official site and on localhost (to catch
+ // analytics bugs when testing locally).
+ // Skip analytics is the fragment has "testing=1", this is used by UI tests.
+ if ((window.location.origin.startsWith('http://localhost:') ||
+ window.location.origin.endsWith('.perfetto.dev')) &&
+ !globals.testing) {
return new AnalyticsImpl();
}
return new NullAnalytics();
@@ -40,6 +45,7 @@
updatePath(_: string): void;
logEvent(_x: TraceCategories|null, _y: string): void;
logError(_x: string, _y?: boolean): void;
+ isEnabled(): boolean;
}
export class NullAnalytics implements Analytics {
@@ -47,6 +53,9 @@
updatePath(_: string) {}
logEvent(_x: TraceCategories|null, _y: string) {}
logError(_x: string) {}
+ isEnabled(): boolean {
+ return false;
+ }
}
class AnalyticsImpl implements Analytics {
@@ -81,7 +90,7 @@
script.src = 'https://www.googletagmanager.com/gtag/js?id=' + ANALYTICS_ID;
script.defer = true;
document.head.appendChild(script);
- const route = globals.state.route || '/';
+ const route = Router.parseUrl(window.location.href).page || '/';
console.log(
`GA initialized. route=${route}`,
`isInternalUser=${globals.isInternalUser}`);
@@ -97,7 +106,7 @@
page_title: PAGE_TITLE,
dimension1: globals.isInternalUser ? '1' : '0',
dimension2: version.VERSION,
- dimension3: globals.channel,
+ dimension3: getCurrentChannel(),
});
this.updatePath(route);
}
@@ -114,4 +123,8 @@
logError(description: string, fatal = true) {
gtagGlobals.gtag('event', 'exception', {description, fatal});
}
+
+ isEnabled(): boolean {
+ return true;
+ }
}
diff --git a/ui/src/frontend/clipboard.ts b/ui/src/frontend/clipboard.ts
index 28d70be..7c9a61d 100644
--- a/ui/src/frontend/clipboard.ts
+++ b/ui/src/frontend/clipboard.ts
@@ -12,6 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {Actions} from '../common/actions';
+import {QueryResponse} from '../common/queries';
+
+import {globals} from './globals';
+
+export function onClickCopy(url: string) {
+ return (e: Event) => {
+ e.preventDefault();
+ copyToClipboard(url);
+ globals.dispatch(Actions.updateStatus(
+ {msg: 'Link copied into the clipboard', timestamp: Date.now() / 1000}));
+ };
+}
+
export async function copyToClipboard(text: string): Promise<void> {
try {
// TODO(hjd): Fix typescript type for navigator.
@@ -21,3 +35,31 @@
console.error(`Failed to copy "${text}" to clipboard: ${err}`);
}
}
+
+export async function queryResponseToClipboard(resp: QueryResponse):
+ Promise<void> {
+ const lines: string[][] = [];
+ lines.push(resp.columns);
+ for (const row of resp.rows) {
+ const line = [];
+ for (const col of resp.columns) {
+ const value = row[col];
+ line.push(value === null ? 'NULL' : value.toString());
+ }
+ lines.push(line);
+ }
+ copyToClipboard(lines.map(line => line.join('\t')).join('\n'));
+}
+
+export function download(file: File, name?: string): void {
+ const url = URL.createObjectURL(file);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = name === undefined ? file.name : name;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ URL.revokeObjectURL(url);
+}
+
+
diff --git a/ui/src/frontend/cookie_consent.ts b/ui/src/frontend/cookie_consent.ts
index 3ea5ecf..607b46f 100644
--- a/ui/src/frontend/cookie_consent.ts
+++ b/ui/src/frontend/cookie_consent.ts
@@ -21,10 +21,15 @@
export class CookieConsent implements m.ClassComponent {
private showCookieConsent = true;
- view() {
- if (this.showCookieConsent) {
- this.showCookieConsent = localStorage.getItem(COOKIE_ACK_KEY) === null;
+ oninit() {
+ this.showCookieConsent = true;
+ if (!globals.logging.isEnabled() ||
+ localStorage.getItem(COOKIE_ACK_KEY) === 'true') {
+ this.showCookieConsent = false;
}
+ }
+
+ view() {
if (!this.showCookieConsent) return;
return m(
'.cookie-consent',
diff --git a/ui/src/frontend/counter_panel.ts b/ui/src/frontend/counter_panel.ts
index 4a3ccd7..eb5d991 100644
--- a/ui/src/frontend/counter_panel.ts
+++ b/ui/src/frontend/counter_panel.ts
@@ -25,8 +25,8 @@
view() {
const counterInfo = globals.counterDetails;
if (counterInfo && counterInfo.startTime &&
- counterInfo.value !== undefined && counterInfo.delta !== undefined &&
- counterInfo.duration !== undefined) {
+ counterInfo.name !== undefined && counterInfo.value !== undefined &&
+ counterInfo.delta !== undefined && counterInfo.duration !== undefined) {
return m(
'.details-panel',
m('.details-panel-heading', m('h2', `Counter Details`)),
@@ -34,6 +34,7 @@
'.details-table',
[m('table.half-width',
[
+ m('tr', m('th', `Name`), m('td', `${counterInfo.name}`)),
m('tr',
m('th', `Start time`),
m('td', `${timeToCode(counterInfo.startTime)}`)),
diff --git a/ui/src/frontend/details_panel.ts b/ui/src/frontend/details_panel.ts
index 9332c00..2e8ce7d 100644
--- a/ui/src/frontend/details_panel.ts
+++ b/ui/src/frontend/details_panel.ts
@@ -15,22 +15,28 @@
import * as m from 'mithril';
import {QueryResponse} from 'src/common/queries';
+import {Actions} from '../common/actions';
import {LogExists, LogExistsKey} from '../common/logs';
+import {DEFAULT_PIVOT_TABLE_ID} from '../common/pivot_table_common';
import {AggregationPanel} from './aggregation_panel';
import {ChromeSliceDetailsPanel} from './chrome_slice_panel';
import {CounterDetailsPanel} from './counter_panel';
import {CpuProfileDetailsPanel} from './cpu_profile_panel';
import {DragGestureHandler} from './drag_gesture_handler';
+import {FlamegraphDetailsPanel} from './flamegraph_panel';
import {
FlowEventsAreaSelectedPanel,
FlowEventsPanel
} from './flow_events_panel';
import {globals} from './globals';
-import {HeapProfileDetailsPanel} from './heap_profile_panel';
import {LogPanel} from './logs_panel';
+import {showModal} from './modal';
import {NotesEditorPanel} from './notes_panel';
import {AnyAttrsVnode, PanelContainer} from './panel_container';
+import {PivotTable} from './pivot_table';
+import {ColumnDisplay, ColumnPicker} from './pivot_table_editor';
+import {PivotTableHelper} from './pivot_table_helper';
import {QueryTable} from './query_table';
import {SliceDetailsPanel} from './slice_panel';
import {ThreadStatePanel} from './thread_state_panel';
@@ -55,6 +61,38 @@
return data && data.exists;
}
+function showPivotTableEditorModal(helper?: PivotTableHelper) {
+ if (helper !== undefined && helper.editPivotTableModalOpen) {
+ let content;
+ if (helper.availableColumns.length === 0 ||
+ helper.availableAggregations.length === 0) {
+ content =
+ m('.pivot-table-editor-container',
+ helper.availableColumns.length === 0 ?
+ m('div', 'No columns available.') :
+ null,
+ helper.availableAggregations.length === 0 ?
+ m('div', 'No aggregations available.') :
+ null);
+ } else {
+ const attrs = {helper};
+ content =
+ m('.pivot-table-editor-container',
+ m(ColumnPicker, attrs),
+ m(ColumnDisplay, attrs));
+ }
+
+ showModal({
+ title: 'Edit Pivot Table',
+ content,
+ buttons: [],
+ }).finally(() => {
+ helper.toggleEditPivotTableModal();
+ globals.rafScheduler.scheduleFullRedraw();
+ });
+ }
+}
+
interface Tab {
key: string;
name: string;
@@ -113,26 +151,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);
+ const activeTabExists = globals.state.currentTab &&
+ attrs.tabs.map(tab => tab.key).includes(globals.state.currentTab);
if (!activeTabExists) {
- globals.frontendLocalState.currentTab = undefined;
+ globals.dispatch(Actions.setCurrentTab({tab: undefined}));
}
const renderTab = (tab: Tab) => {
- if (globals.frontendLocalState.currentTab === tab.key ||
- globals.frontendLocalState.currentTab === undefined &&
- attrs.tabs.keys().next().value === tab.key) {
+ if (globals.state.currentTab === tab.key ||
+ globals.state.currentTab === undefined &&
+ attrs.tabs[0].key === tab.key) {
// Update currentTab in case we didn't have one before.
- globals.frontendLocalState.currentTab = tab.key;
+ globals.dispatch(Actions.setCurrentTab({tab: tab.key}));
return m('.tab[active]', tab.name);
}
return m(
'.tab',
{
onclick: () => {
- globals.frontendLocalState.currentTab = tab.key;
- globals.rafScheduler.scheduleFullRedraw();
+ globals.dispatch(Actions.setCurrentTab({tab: tab.key}));
}
},
tab.name);
@@ -232,11 +268,12 @@
})
});
break;
+ case 'PERF_SAMPLES':
case 'HEAP_PROFILE':
detailsPanels.push({
key: 'current_selection',
name: 'Current Selection',
- vnode: m(HeapProfileDetailsPanel, {key: 'heap_profile'})
+ vnode: m(FlamegraphDetailsPanel, {key: 'flamegraph'})
});
break;
case 'CPU_PROFILE_SAMPLE':
@@ -284,6 +321,24 @@
});
}
+ for (const pivotTableId of Object.keys(globals.state.pivotTable)) {
+ const pivotTable = globals.state.pivotTable[pivotTableId];
+ const helper = globals.pivotTableHelper.get(pivotTableId);
+ if (pivotTableId !== DEFAULT_PIVOT_TABLE_ID ||
+ globals.frontendLocalState.showPivotTable) {
+ if (helper !== undefined) {
+ helper.setSelectedPivotsAndAggregations(
+ pivotTable.selectedPivots, pivotTable.selectedAggregations);
+ }
+ detailsPanels.push({
+ key: pivotTableId,
+ name: pivotTable.name,
+ vnode: m(PivotTable, {key: pivotTableId, pivotTableId, helper})
+ });
+ }
+ showPivotTableEditorModal(helper);
+ }
+
if (globals.connectedFlows.length > 0) {
detailsPanels.push({
key: 'bound_flows',
@@ -313,8 +368,8 @@
this.showDetailsPanel = detailsPanels.length > 0;
- const currentTabDetails = detailsPanels.filter(
- tab => tab.key === globals.frontendLocalState.currentTab)[0];
+ const currentTabDetails =
+ detailsPanels.filter(tab => tab.key === globals.state.currentTab)[0];
const panel = currentTabDetails ?
currentTabDetails.vnode :
diff --git a/ui/src/frontend/file_drop_handler.ts b/ui/src/frontend/file_drop_handler.ts
index 8eccc4d..89f38c0 100644
--- a/ui/src/frontend/file_drop_handler.ts
+++ b/ui/src/frontend/file_drop_handler.ts
@@ -42,7 +42,6 @@
if (evt.dataTransfer && dragEventHasFiles(evt)) {
const file = evt.dataTransfer.files[0];
if (file) {
- globals.frontendLocalState.localOnlyMode = false;
globals.dispatch(Actions.openTraceFromFile({file}));
}
}
diff --git a/ui/src/frontend/flags_page.ts b/ui/src/frontend/flags_page.ts
new file mode 100644
index 0000000..5c04d99
--- /dev/null
+++ b/ui/src/frontend/flags_page.ts
@@ -0,0 +1,142 @@
+// 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 {channelChanged, getNextChannel, setChannel} from '../common/channels';
+import {featureFlags, Flag, OverrideState} from '../common/feature_flags';
+
+import {globals} from './globals';
+import {createPage} from './pages';
+
+const RELEASE_PROCESS_URL =
+ 'https://perfetto.dev/docs/visualization/perfetto-ui-release-process';
+
+interface FlagOption {
+ id: string;
+ name: string;
+}
+
+interface SelectWidgetAttrs {
+ label: string;
+ description: m.Children;
+ options: FlagOption[];
+ selected: string;
+ onSelect: (id: string) => void;
+}
+
+class SelectWidget implements m.ClassComponent<SelectWidgetAttrs> {
+ view(vnode: m.Vnode<SelectWidgetAttrs>) {
+ const attrs = vnode.attrs;
+ return m(
+ '.flag-widget',
+ m('label', attrs.label),
+ m(
+ 'select',
+ {
+ onchange: (e: InputEvent) => {
+ const value = (e.target as HTMLSelectElement).value;
+ attrs.onSelect(value);
+ globals.rafScheduler.scheduleFullRedraw();
+ },
+ },
+ attrs.options.map(o => {
+ const selected = o.id === attrs.selected;
+ return m('option', {value: o.id, selected}, o.name);
+ }),
+ ),
+ m('.description', attrs.description),
+ );
+ }
+}
+
+interface FlagWidgetAttrs {
+ flag: Flag;
+}
+
+class FlagWidget implements m.ClassComponent<FlagWidgetAttrs> {
+ view(vnode: m.Vnode<FlagWidgetAttrs>) {
+ const flag = vnode.attrs.flag;
+ const defaultState = flag.defaultValue ? 'Enabled' : 'Disabled';
+ return m(SelectWidget, {
+ label: flag.name,
+ description: flag.description,
+ options: [
+ {id: OverrideState.DEFAULT, name: `Default (${defaultState})`},
+ {id: OverrideState.TRUE, name: 'Enabled'},
+ {id: OverrideState.FALSE, name: 'Disabled'},
+ ],
+ selected: flag.overriddenState(),
+ onSelect: (value: string) => {
+ switch (value) {
+ case OverrideState.TRUE:
+ flag.set(true);
+ break;
+ case OverrideState.FALSE:
+ flag.set(false);
+ break;
+ default:
+ case OverrideState.DEFAULT:
+ flag.reset();
+ break;
+ }
+ }
+ });
+ }
+}
+
+export const FlagsPage = createPage({
+ view() {
+ const needsReload = channelChanged();
+ return m(
+ '.flags-page',
+ m(
+ '.flags-content',
+ m('h1', 'Feature flags'),
+ needsReload &&
+ [
+ m('h2', 'Please reload for your changes to take effect'),
+ ],
+ m(SelectWidget, {
+ label: 'Release channel',
+ description: [
+ 'Which release channel of the UI to use. See ',
+ m('a',
+ {
+ href: RELEASE_PROCESS_URL,
+ },
+ 'Release Process'),
+ ' for more information.'
+ ],
+ options: [
+ {id: 'stable', name: 'Stable (default)'},
+ {id: 'canary', name: 'Canary'},
+ {id: 'autopush', name: 'Autopush'},
+ ],
+ selected: getNextChannel(),
+ onSelect: id => setChannel(id),
+ }),
+ m('button',
+ {
+ onclick: () => {
+ featureFlags.resetAll();
+ globals.rafScheduler.scheduleFullRedraw();
+ },
+ },
+ 'Reset all below'),
+
+ featureFlags.allFlags().map(flag => m(FlagWidget, {flag})),
+ ));
+ }
+});
diff --git a/ui/src/frontend/flamegraph.ts b/ui/src/frontend/flamegraph.ts
index 8836c11..afa5f7f 100644
--- a/ui/src/frontend/flamegraph.ts
+++ b/ui/src/frontend/flamegraph.ts
@@ -33,7 +33,7 @@
// below the box.
const NODE_HEIGHT = 18;
-export const HEAP_PROFILE_HOVERED_COLOR = 'hsl(224, 45%, 55%)';
+export const FLAMEGRAPH_HOVERED_COLOR = 'hsl(224, 45%, 55%)';
export function findRootSize(data: CallsiteInfo[]) {
let totalSize = 0;
diff --git a/ui/src/frontend/heap_profile_panel.ts b/ui/src/frontend/flamegraph_panel.ts
similarity index 65%
rename from ui/src/frontend/heap_profile_panel.ts
rename to ui/src/frontend/flamegraph_panel.ts
index c444268..62a315d 100644
--- a/ui/src/frontend/heap_profile_panel.ts
+++ b/ui/src/frontend/flamegraph_panel.ts
@@ -14,17 +14,16 @@
import * as m from 'mithril';
+import {assertExists} from '../base/logging';
import {Actions} from '../common/actions';
import {
ALLOC_SPACE_MEMORY_ALLOCATED_KEY,
OBJECTS_ALLOCATED_KEY,
OBJECTS_ALLOCATED_NOT_FREED_KEY,
+ PERF_SAMPLES_KEY,
SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY,
} from '../common/flamegraph_util';
-import {
- CallsiteInfo,
- HeapProfileFlamegraphViewingOption
-} from '../common/state';
+import {CallsiteInfo, FlamegraphStateViewingOption} from '../common/state';
import {timeToCode} from '../common/time';
import {PerfettoMouseEvent} from './events';
@@ -32,14 +31,17 @@
import {globals} from './globals';
import {Panel, PanelSize} from './panel';
import {debounce} from './rate_limiters';
+import {getCurrentTrace} from './sidebar';
+import {convertTraceToPprofAndDownload} from './trace_converter';
-interface HeapProfileDetailsPanelAttrs {}
+interface FlamegraphDetailsPanelAttrs {}
const HEADER_HEIGHT = 30;
enum ProfileType {
NATIVE_HEAP_PROFILE = 'native',
JAVA_HEAP_GRAPH = 'graph',
+ PERF_SAMPLE = 'perf'
}
function isProfileType(s: string): s is ProfileType {
@@ -69,8 +71,7 @@
totalSize: 'Subtree objects',
};
-export class HeapProfileDetailsPanel extends
- Panel<HeapProfileDetailsPanelAttrs> {
+export class FlamegraphDetailsPanel extends Panel<FlamegraphDetailsPanelAttrs> {
private profileType?: ProfileType = undefined;
private ts = 0;
private pid = 0;
@@ -81,18 +82,20 @@
}, 20);
view() {
- const heapDumpInfo = globals.heapProfileDetails;
- if (heapDumpInfo && heapDumpInfo.type !== undefined &&
- heapDumpInfo.ts !== undefined && heapDumpInfo.tsNs !== undefined &&
- heapDumpInfo.pid !== undefined && heapDumpInfo.upid !== undefined) {
- this.profileType = toProfileType(heapDumpInfo.type);
- this.ts = heapDumpInfo.tsNs;
- this.pid = heapDumpInfo.pid;
- if (heapDumpInfo.flamegraph) {
+ const flamegraphDetails = globals.flamegraphDetails;
+ if (flamegraphDetails && flamegraphDetails.type !== undefined &&
+ flamegraphDetails.ts !== undefined &&
+ flamegraphDetails.tsNs !== undefined &&
+ flamegraphDetails.pid !== undefined &&
+ flamegraphDetails.upid !== undefined) {
+ this.profileType = toProfileType(flamegraphDetails.type);
+ this.ts = flamegraphDetails.tsNs;
+ this.pid = flamegraphDetails.pid;
+ if (flamegraphDetails.flamegraph) {
this.flamegraph.updateDataIfChanged(
- this.nodeRendering(), heapDumpInfo.flamegraph);
+ this.nodeRendering(), flamegraphDetails.flamegraph);
}
- const height = heapDumpInfo.flamegraph ?
+ const height = flamegraphDetails.flamegraph ?
this.flamegraph.getHeight() + HEADER_HEIGHT :
0;
return m(
@@ -116,7 +119,7 @@
}
}
},
- m('.details-panel-heading.heap-profile',
+ m('.details-panel-heading.flamegraph-profile',
{onclick: (e: MouseEvent) => e.stopPropagation()},
[
m('div.options',
@@ -128,9 +131,10 @@
[
m('div.selected',
`Selected function: ${
- toSelectedCallsite(heapDumpInfo.expandedCallsite)}`),
+ toSelectedCallsite(
+ flamegraphDetails.expandedCallsite)}`),
m('div.time',
- `Snapshot time: ${timeToCode(heapDumpInfo.ts)}`),
+ `Snapshot time: ${timeToCode(flamegraphDetails.ts)}`),
m('input[type=text][placeholder=Focus]', {
oninput: (e: Event) => {
const target = (e.target as HTMLInputElement);
@@ -157,7 +161,7 @@
} else {
return m(
'.details-panel',
- m('.details-panel-heading', m('h2', `Heap Profile`)));
+ m('.details-panel-heading', m('h2', `Flamegraph Profile`)));
}
}
@@ -167,6 +171,8 @@
return 'Heap Profile:';
case ProfileType.JAVA_HEAP_GRAPH:
return 'Java Heap:';
+ case ProfileType.PERF_SAMPLE:
+ return 'Perf sample:';
default:
throw new Error('unknown type');
}
@@ -176,87 +182,49 @@
if (this.profileType === undefined) {
return {};
}
- const viewingOption =
- globals.state.currentHeapProfileFlamegraph!.viewingOption;
+ const viewingOption = globals.state.currentFlamegraphState!.viewingOption;
switch (this.profileType) {
- case ProfileType.NATIVE_HEAP_PROFILE:
- return RENDER_SELF_AND_TOTAL;
case ProfileType.JAVA_HEAP_GRAPH:
if (viewingOption === OBJECTS_ALLOCATED_NOT_FREED_KEY) {
return RENDER_OBJ_COUNT;
} else {
return RENDER_SELF_AND_TOTAL;
}
+ case ProfileType.NATIVE_HEAP_PROFILE:
+ case ProfileType.PERF_SAMPLE:
+ return RENDER_SELF_AND_TOTAL;
default:
throw new Error('unknown type');
}
}
private updateFocusRegex() {
- globals.dispatch(Actions.changeFocusHeapProfileFlamegraph({
+ globals.dispatch(Actions.changeFocusFlamegraphState({
focusRegex: this.focusRegex,
}));
}
- getButtonsClass(button: HeapProfileFlamegraphViewingOption): string {
- if (globals.state.currentHeapProfileFlamegraph === null) return '';
- return globals.state.currentHeapProfileFlamegraph.viewingOption === button ?
- '.chosen' :
- '';
- }
-
getViewingOptionButtons(): m.Children {
- const viewingOptions = [
- m(`button${this.getButtonsClass(SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY)}`,
- {
- onclick: () => {
- this.changeViewingOption(SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY);
- }
- },
- 'space'),
- m(`button${this.getButtonsClass(OBJECTS_ALLOCATED_NOT_FREED_KEY)}`,
- {
- onclick: () => {
- this.changeViewingOption(OBJECTS_ALLOCATED_NOT_FREED_KEY);
- }
- },
- 'objects'),
- ];
-
- if (this.profileType === ProfileType.NATIVE_HEAP_PROFILE) {
- viewingOptions.push(
- m(`button${this.getButtonsClass(ALLOC_SPACE_MEMORY_ALLOCATED_KEY)}`,
- {
- onclick: () => {
- this.changeViewingOption(ALLOC_SPACE_MEMORY_ALLOCATED_KEY);
- }
- },
- 'alloc space'),
- m(`button${this.getButtonsClass(OBJECTS_ALLOCATED_KEY)}`,
- {
- onclick: () => {
- this.changeViewingOption(OBJECTS_ALLOCATED_KEY);
- }
- },
- 'alloc objects'));
- }
- return m('div', ...viewingOptions);
- }
-
- changeViewingOption(viewingOption: HeapProfileFlamegraphViewingOption) {
- globals.dispatch(Actions.changeViewHeapProfileFlamegraph({viewingOption}));
+ return m(
+ 'div',
+ ...FlamegraphDetailsPanel.selectViewingOptions(
+ assertExists(this.profileType)));
}
downloadPprof() {
const engine = Object.values(globals.state.engines)[0];
if (!engine) return;
- const src = engine.source;
- globals.dispatch(
- Actions.convertTraceToPprof({pid: this.pid, ts1: this.ts, src}));
+ getCurrentTrace()
+ .then(file => {
+ convertTraceToPprofAndDownload(file, this.pid, this.ts);
+ })
+ .catch(error => {
+ throw new Error(`Failed to get current trace ${error}`);
+ });
}
private changeFlamegraphData() {
- const data = globals.heapProfileDetails;
+ const data = globals.flamegraphDetails;
const flamegraphData = data.flamegraph === undefined ? [] : data.flamegraph;
this.flamegraph.updateDataIfChanged(
this.nodeRendering(), flamegraphData, data.expandedCallsite);
@@ -264,7 +232,7 @@
renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
this.changeFlamegraphData();
- const current = globals.state.currentHeapProfileFlamegraph;
+ const current = globals.state.currentFlamegraphState;
if (current === null) return;
const unit =
current.viewingOption === SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY ||
@@ -276,7 +244,7 @@
onMouseClick({x, y}: {x: number, y: number}): boolean {
const expandedCallsite = this.flamegraph.onMouseClick({x, y});
- globals.dispatch(Actions.expandHeapProfileFlamegraph({expandedCallsite}));
+ globals.dispatch(Actions.expandFlamegraphState({expandedCallsite}));
return true;
}
@@ -288,4 +256,46 @@
onMouseOut() {
this.flamegraph.onMouseOut();
}
+
+ private static selectViewingOptions(profileType: ProfileType) {
+ switch (profileType) {
+ case ProfileType.PERF_SAMPLE:
+ return [this.buildButtonComponent(PERF_SAMPLES_KEY, 'samples')];
+ case ProfileType.NATIVE_HEAP_PROFILE:
+ return [
+ this.buildButtonComponent(
+ SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY, 'space'),
+ this.buildButtonComponent(OBJECTS_ALLOCATED_NOT_FREED_KEY, 'objects')
+ ];
+ case ProfileType.JAVA_HEAP_GRAPH:
+ return [
+ this.buildButtonComponent(
+ SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY, 'space'),
+ this.buildButtonComponent(OBJECTS_ALLOCATED_NOT_FREED_KEY, 'objects'),
+ this.buildButtonComponent(
+ ALLOC_SPACE_MEMORY_ALLOCATED_KEY, 'alloc space'),
+ this.buildButtonComponent(OBJECTS_ALLOCATED_KEY, 'alloc objects')
+ ];
+ default:
+ throw new Error(`Unexpected profile type ${profileType}`);
+ }
+ }
+
+ private static buildButtonComponent(
+ viewingOption: FlamegraphStateViewingOption, text: string) {
+ const buttonsClass =
+ (globals.state.currentFlamegraphState &&
+ globals.state.currentFlamegraphState.viewingOption === viewingOption) ?
+ '.chosen' :
+ '';
+ return m(
+ `button${buttonsClass}`,
+ {
+ onclick: () => {
+ globals.dispatch(
+ Actions.changeViewFlamegraphState({viewingOption}));
+ }
+ },
+ text);
+ }
}
diff --git a/ui/src/frontend/flow_events_panel.ts b/ui/src/frontend/flow_events_panel.ts
index 6f15468..6ed7656 100644
--- a/ui/src/frontend/flow_events_panel.ts
+++ b/ui/src/frontend/flow_events_panel.ts
@@ -82,9 +82,10 @@
const args = {
onclick: () => flowClickHandler(otherEnd.sliceId, otherEnd.trackId),
- onmousemove: () =>
- globals.frontendLocalState.setHighlightedSliceId(otherEnd.sliceId),
- onmouseleave: () => globals.frontendLocalState.setHighlightedSliceId(-1)
+ onmousemove: () => globals.dispatch(
+ Actions.setHighlightedSliceId({sliceId: otherEnd.sliceId})),
+ onmouseleave: () =>
+ globals.dispatch(Actions.setHighlightedSliceId({sliceId: -1})),
};
const data = [
diff --git a/ui/src/frontend/flow_events_renderer.ts b/ui/src/frontend/flow_events_renderer.ts
index 33b7dab..c435ef8 100644
--- a/ui/src/frontend/flow_events_renderer.ts
+++ b/ui/src/frontend/flow_events_renderer.ts
@@ -212,11 +212,10 @@
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;
+ const highlighted = flow.end.sliceId === globals.state.highlightedSliceId ||
+ flow.begin.sliceId === globals.state.highlightedSliceId;
+ const focused = flow.id === globals.state.focusedFlowIdLeft ||
+ flow.id === globals.state.focusedFlowIdRight;
let intensity = DEFAULT_FLOW_INTENSITY;
let width = DEFAULT_FLOW_WIDTH;
diff --git a/ui/src/frontend/frontend_local_state.ts b/ui/src/frontend/frontend_local_state.ts
index 4349f81..b09327b 100644
--- a/ui/src/frontend/frontend_local_state.ts
+++ b/ui/src/frontend/frontend_local_state.ts
@@ -35,7 +35,10 @@
function chooseLatest<T extends Timestamped<{}>>(current: T, next: T): T {
if (next !== current && next.lastUpdate > current.lastUpdate) {
- return next;
+ // |next| is from state. Callers may mutate the return value of
+ // this function so we need to clone |next| to prevent bad mutations
+ // of state:
+ return Object.assign({}, next);
}
return current;
}
@@ -65,26 +68,14 @@
export class FrontendLocalState {
visibleWindowTime = new TimeSpan(0, 10);
timeScale = new TimeScale(this.visibleWindowTime, [0, 0]);
- perfDebug = false;
- hoveredUtid = -1;
- 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;
- currentTab?: string;
scrollToTrackId?: string|number;
httpRpcState: HttpRpcState = {connected: false};
newVersionAvailable = false;
+ showPivotTable = false;
// This is used to calculate the tracks within a Y range for area selection.
areaY: Range = {};
@@ -117,70 +108,15 @@
return this.scrollBarWidth;
}
- togglePerfDebug() {
- this.perfDebug = !this.perfDebug;
+ setHttpRpcState(httpRpcState: HttpRpcState) {
+ this.httpRpcState = httpRpcState;
globals.rafScheduler.scheduleFullRedraw();
}
- setHoveredUtidAndPid(utid: number, pid: number) {
- this.hoveredUtid = utid;
- this.hoveredPid = pid;
- 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;
- this.hoveredLogsTimestamp = ts;
- globals.rafScheduler.scheduleRedraw();
- }
-
- setHoveredNoteTimestamp(ts: number) {
- if (this.hoveredNoteTimestamp === ts) return;
- this.hoveredNoteTimestamp = ts;
- globals.rafScheduler.scheduleRedraw();
- }
-
- setVidTimestamp(ts: number) {
- if (this.vidTimestamp === ts) return;
- this.vidTimestamp = ts;
- globals.rafScheduler.scheduleRedraw();
- }
-
addVisibleTrack(trackId: string) {
this.visibleTracks.add(trackId);
}
- setSearchIndex(index: number) {
- this.searchIndex = index;
- globals.rafScheduler.scheduleRedraw();
- }
-
- toggleSidebar() {
- this.sidebarVisible = !this.sidebarVisible;
- globals.rafScheduler.scheduleFullRedraw();
- }
-
- setHttpRpcState(httpRpcState: HttpRpcState) {
- this.httpRpcState = httpRpcState;
- globals.rafScheduler.scheduleFullRedraw();
- }
-
// Called when beginning a canvas redraw.
clearVisibleTracks() {
this.visibleTracks.clear();
@@ -197,10 +133,24 @@
}
}
+ togglePivotTable() {
+ this.showPivotTable = !this.showPivotTable;
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+
mergeState(state: FrontendState): void {
+ // This is unfortunately subtle. This class mutates this._visibleState.
+ // Since we may not mutate |state| (in order to make immer's immutable
+ // updates work) this means that we have to make a copy of the visibleState.
+ // when updating it. We don't want to have to do that unnecessarily so
+ // chooseLatest returns a shallow clone of state.visibleState *only* when
+ // that is the newer state. All of these complications should vanish when
+ // we remove this class.
+ const previousVisibleState = this._visibleState;
this._omniboxState = chooseLatest(this._omniboxState, state.omniboxState);
this._visibleState = chooseLatest(this._visibleState, state.visibleState);
- if (this._visibleState === state.visibleState) {
+ const visibleStateWasUpdated = previousVisibleState !== this._visibleState;
+ if (visibleStateWasUpdated) {
this.updateLocalTime(
new TimeSpan(this._visibleState.startSec, this._visibleState.endSec));
}
@@ -225,7 +175,7 @@
}
private setOmniboxDebounced = debounce(() => {
- globals.dispatch(Actions.setOmnibox(this._omniboxState));
+ globals.dispatch(Actions.setOmnibox({...this._omniboxState}));
}, 20);
setOmnibox(value: string, mode: 'SEARCH'|'COMMAND') {
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 604ef52..904a371 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -13,7 +13,7 @@
// limitations under the License.
import {assertExists} from '../base/logging';
-import {DeferredAction} from '../common/actions';
+import {Actions, DeferredAction} from '../common/actions';
import {AggregateData} from '../common/aggregation_data';
import {Args, ArgsTree} from '../common/arg_types';
import {
@@ -27,12 +27,15 @@
import {Analytics, initAnalytics} from './analytics';
import {FrontendLocalState} from './frontend_local_state';
+import {PivotTableHelper} from './pivot_table_helper';
import {RafScheduler} from './raf_scheduler';
+import {Router} from './router';
import {ServiceWorkerController} from './service_worker_controller';
type Dispatch = (action: DeferredAction) => void;
type TrackDataStore = Map<string, {}>;
-type QueryResultsStore = Map<string, {}>;
+type QueryResultsStore = Map<string, {}|undefined>;
+type PivotTableHelperStore = Map<string, PivotTableHelper>;
type AggregateDataStore = Map<string, AggregateData>;
type Description = Map<string, string>;
export interface SliceDetails {
@@ -81,6 +84,7 @@
value?: number;
delta?: number;
duration?: number;
+ name?: string;
}
export interface ThreadStateDetails {
@@ -93,7 +97,7 @@
blockedFunction?: string;
}
-export interface HeapProfileDetails {
+export interface FlamegraphDetails {
type?: string;
id?: number;
ts?: number;
@@ -133,7 +137,14 @@
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;
+ const script = document.currentScript as HTMLScriptElement;
+
+ // Needed for DOM tests, that do not have script element.
+ if (script === null) {
+ return '';
+ }
+
+ let root = script.src;
root = root.substr(0, root.lastIndexOf('/') + 1);
return root;
}
@@ -144,19 +155,19 @@
class Globals {
readonly root = getRoot();
+ private _testing = false;
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;
private _queryResults?: QueryResultsStore = undefined;
+ private _pivotTableHelper?: PivotTableHelperStore = undefined;
private _overviewStore?: OverviewStore = undefined;
private _aggregateDataStore?: AggregateDataStore = undefined;
private _threadMap?: ThreadMap = undefined;
@@ -166,7 +177,7 @@
private _selectedFlows?: Flow[] = undefined;
private _visibleFlowCategories?: Map<string, boolean> = undefined;
private _counterDetails?: CounterDetails = undefined;
- private _heapProfileDetails?: HeapProfileDetails = undefined;
+ private _flamegraphDetails?: FlamegraphDetails = undefined;
private _cpuProfileDetails?: CpuProfileDetails = undefined;
private _numQueriesQueued = 0;
private _bufferUsage?: number = undefined;
@@ -176,11 +187,15 @@
private _metricResult?: MetricResult = undefined;
private _hasFtrace?: boolean = undefined;
private _jobStatus?: Map<ConversionJobName, ConversionJobStatus> = undefined;
+ private _router?: Router = undefined;
+
+ // TODO(hjd): Remove once we no longer need to update UUID on redraw.
+ private _publishRedraw?: () => void = undefined;
private _currentSearchResults: CurrentSearchResults = {
- sliceIds: [],
- tsStarts: [],
- utids: [],
+ sliceIds: new Float64Array(0),
+ tsStarts: new Float64Array(0),
+ utids: new Float64Array(0),
trackIds: [],
sources: [],
totalResults: 0,
@@ -191,18 +206,21 @@
count: new Uint8Array(0),
};
- initialize(dispatch: Dispatch, controllerWorker: Worker) {
+ initialize(dispatch: Dispatch, router: Router) {
this._dispatch = dispatch;
- this._controllerWorker = controllerWorker;
+ this._router = router;
this._state = createEmptyState();
this._frontendLocalState = new FrontendLocalState();
this._rafScheduler = new RafScheduler();
this._serviceWorkerController = new ServiceWorkerController();
+ this._testing =
+ self.location && self.location.search.indexOf('testing=1') >= 0;
this._logging = initAnalytics();
// TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
this._trackDataStore = new Map<string, {}>();
this._queryResults = new Map<string, {}>();
+ this._pivotTableHelper = new Map<string, PivotTableHelper>();
this._overviewStore = new Map<string, QuantizedLoad[]>();
this._aggregateDataStore = new Map<string, AggregateData>();
this._threadMap = new Map<number, ThreadDesc>();
@@ -212,10 +230,22 @@
this._visibleFlowCategories = new Map<string, boolean>();
this._counterDetails = {};
this._threadStateDetails = {};
- this._heapProfileDetails = {};
+ this._flamegraphDetails = {};
this._cpuProfileDetails = {};
}
+ get router(): Router {
+ return assertExists(this._router);
+ }
+
+ get publishRedraw(): () => void {
+ return this._publishRedraw || (() => {});
+ }
+
+ set publishRedraw(f: () => void) {
+ this._publishRedraw = f;
+ }
+
get state(): State {
return assertExists(this._state);
}
@@ -257,6 +287,10 @@
return assertExists(this._queryResults);
}
+ get pivotTableHelper(): PivotTableHelperStore {
+ return assertExists(this._pivotTableHelper);
+ }
+
get threads() {
return assertExists(this._threadMap);
}
@@ -313,12 +347,12 @@
return assertExists(this._aggregateDataStore);
}
- get heapProfileDetails() {
- return assertExists(this._heapProfileDetails);
+ get flamegraphDetails() {
+ return assertExists(this._flamegraphDetails);
}
- set heapProfileDetails(click: HeapProfileDetails) {
- this._heapProfileDetails = assertExists(click);
+ set flamegraphDetails(click: FlamegraphDetails) {
+ this._flamegraphDetails = assertExists(click);
}
get traceErrors() {
@@ -454,9 +488,9 @@
makeSelection(action: DeferredAction<{}>, tabToOpen = 'current_selection') {
// A new selection should cancel the current search selection.
- globals.frontendLocalState.searchIndex = -1;
- globals.frontendLocalState.currentTab =
- action.type === 'deselect' ? undefined : tabToOpen;
+ globals.dispatch(Actions.setSearchIndex({index: -1}));
+ const tab = action.type === 'deselect' ? undefined : tabToOpen;
+ globals.dispatch(Actions.setCurrentTab({tab}));
globals.dispatch(action);
}
@@ -470,6 +504,7 @@
// TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
this._trackDataStore = undefined;
this._queryResults = undefined;
+ this._pivotTableHelper = undefined;
this._overviewStore = undefined;
this._threadMap = undefined;
this._sliceDetails = undefined;
@@ -478,9 +513,9 @@
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,
@@ -505,11 +540,8 @@
this._isInternalUser = value;
}
- get channel() {
- if (this._channel === undefined) {
- this._channel = localStorage.getItem('perfettoUiChannel') || 'stable';
- }
- return this._channel;
+ get testing() {
+ return this._testing;
}
// Used when switching to the legacy TraceViewer UI.
@@ -517,7 +549,6 @@
// however pending RAFs and workers seem to outlive the |window| and need to
// be cleaned up explicitly.
shutdown() {
- this._controllerWorker!.terminate();
this._rafScheduler!.shutdown();
}
}
diff --git a/ui/src/frontend/help_modal.ts b/ui/src/frontend/help_modal.ts
index eac16aa..62dbab1 100644
--- a/ui/src/frontend/help_modal.ts
+++ b/ui/src/frontend/help_modal.ts
@@ -16,6 +16,7 @@
import * as m from 'mithril';
import {globals} from './globals';
+import {PIVOT_TABLE_FLAG} from './keyboard_event_handler';
import {hideModel, showModal} from './modal';
let helpModelOpen = false;
@@ -94,6 +95,9 @@
m('tr',
m('td', keycap('Ctrl'), ' + ', keycap('b')),
m('td', 'Toggle display of sidebar')),
+ PIVOT_TABLE_FLAG.get() ?
+ m('tr', m('td', keycap('p')), m('td', 'Show pivot table')) :
+ null,
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..9cf48cf 100644
--- a/ui/src/frontend/home_page.ts
+++ b/ui/src/frontend/home_page.ts
@@ -13,11 +13,12 @@
// limitations under the License.
import * as m from 'mithril';
-import {globals} from './globals';
+import {channelChanged, getNextChannel, setChannel} from '../common/channels';
+
+import {globals} from './globals';
import {createPage} from './pages';
-let channelChanged = false;
export const HomePage = createPage({
view() {
@@ -37,7 +38,7 @@
mkChan('canary'),
m('.highlight'),
),
- m(`.home-page-reload${channelChanged ? '.show' : ''}`,
+ m(`.home-page-reload${channelChanged() ? '.show' : ''}`,
'You need to reload the page for the changes to have effect'),
),
),
@@ -48,17 +49,13 @@
});
function mkChan(chan: string) {
- const checked =
- !channelChanged && globals.channel === chan ? '[checked=true]' : '';
+ const checked = getNextChannel() === chan ? '[checked=true]' : '';
return [
- m(`input[type=radio][name=chan][id=chan_${chan}]${checked}`,
- {onchange: () => changeChannel(chan)}),
+ m(`input[type=radio][name=chan][id=chan_${chan}]${checked}`, {
+ onchange: () => {
+ setChannel(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 80712cf..8a86027 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -12,292 +12,109 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import '../tracks/all_frontend';
-
-import {applyPatches, Patch} from 'immer';
+import {Patch, produce} from 'immer';
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';
-import {AggregateData} from '../common/aggregation_data';
-import {ConversionJobStatusUpdate} from '../common/conversion_jobs';
+import {Actions, DeferredAction, StateActions} from '../common/actions';
+import {initializeImmerJs} from '../common/immer_init';
+import {createEmptyState, State} from '../common/state';
+import {initWasm} from '../common/wasm_engine_proxy';
+import {ControllerWorkerInitMessage} from '../common/worker_messages';
import {
- LogBoundsKey,
- LogEntriesKey,
- LogExists,
- LogExistsKey
-} from '../common/logs';
-import {MetricResult} from '../common/metric_data';
-import {CurrentSearchResults, SearchSummary} from '../common/search_data';
-import {
- ControllerWorkerInitMessage,
- EngineWorkerInitMessage
-} from '../common/worker_messages';
+ isGetCategoriesResponse
+} from '../controller/chrome_proxy_record_controller';
+import {initController} from '../controller/index';
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
-} from './globals';
+import {FlagsPage} from './flags_page';
+import {globals} 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 {maybeOpenTraceFromRoute} from './trace_url_handler';
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);
-}
-
-let idleWasmWorker: Worker;
-let activeWasmWorker: Worker;
-
-/**
- * The API the main thread exposes to the controller.
- */
class FrontendApi {
- constructor(private router: Router) {}
+ private port: MessagePort;
+ private state: State;
- patchState(patches: Patch[]) {
- const oldState = globals.state;
- globals.state = applyPatches(globals.state, patches);
+ constructor(port: MessagePort) {
+ this.state = createEmptyState();
+ this.port = port;
+ }
+
+ dispatchMultiple(actions: DeferredAction[]) {
+ const oldState = this.state;
+ const patches: Patch[] = [];
+ for (const action of actions) {
+ const originalLength = patches.length;
+ const morePatches = this.applyAction(action);
+ patches.length += morePatches.length;
+ for (let i = 0; i < morePatches.length; ++i) {
+ patches[i + originalLength] = morePatches[i];
+ }
+ }
+
+ if (this.state === oldState) {
+ return;
+ }
+
+ // Update overall state.
+ globals.state = this.state;
// If the visible time in the global state has been updated more recently
// than the visible time handled by the frontend @ 60fps, update it. This
// typically happens when restoring the state from a permalink.
- globals.frontendLocalState.mergeState(globals.state.frontendLocalState);
+ globals.frontendLocalState.mergeState(this.state.frontendLocalState);
// Only redraw if something other than the frontendLocalState changed.
- for (const key in globals.state) {
+ for (const key in this.state) {
if (key !== 'frontendLocalState' && key !== 'visibleTracks' &&
- oldState[key] !== globals.state[key]) {
- this.redraw();
- return;
+ oldState[key] !== this.state[key]) {
+ globals.rafScheduler.scheduleFullRedraw();
+ break;
}
}
- }
- // TODO: we can't have a publish method for each batch of data that we don't
- // want to keep in the global state. Figure out a more generic and type-safe
- // mechanism to achieve this.
-
- publishOverviewData(data: {[key: string]: QuantizedLoad|QuantizedLoad[]}) {
- for (const [key, value] of Object.entries(data)) {
- if (!globals.overviewStore.has(key)) {
- globals.overviewStore.set(key, []);
- }
- if (value instanceof Array) {
- globals.overviewStore.get(key)!.push(...value);
- } else {
- globals.overviewStore.get(key)!.push(value);
- }
- }
- globals.rafScheduler.scheduleRedraw();
- }
-
- publishTrackData(args: {id: string, data: {}}) {
- globals.setTrackData(args.id, args.data);
- if ([LogExistsKey, LogBoundsKey, LogEntriesKey].includes(args.id)) {
- const data = globals.trackDataStore.get(LogExistsKey) as LogExists;
- if (data && data.exists) globals.rafScheduler.scheduleFullRedraw();
- } else {
- globals.rafScheduler.scheduleRedraw();
+ if (patches.length > 0) {
+ this.port.postMessage(patches);
}
}
- publishQueryResult(args: {id: string, data: {}}) {
- globals.queryResults.set(args.id, args.data);
- this.redraw();
+ private applyAction(action: DeferredAction): Patch[] {
+ const patches: Patch[] = [];
+
+ // 'produce' creates a immer proxy which wraps the current state turning
+ // all imperative mutations of the state done in the callback into
+ // immutable changes to the returned state.
+ this.state = produce(
+ this.state,
+ draft => {
+ // tslint:disable-next-line no-any
+ (StateActions as any)[action.type](draft, action.args);
+ },
+ (morePatches, _) => {
+ const originalLength = patches.length;
+ patches.length += morePatches.length;
+ for (let i = 0; i < morePatches.length; ++i) {
+ patches[i + originalLength] = morePatches[i];
+ }
+ });
+ return patches;
}
- publishThreads(data: ThreadDesc[]) {
- globals.threads.clear();
- data.forEach(thread => {
- globals.threads.set(thread.utid, thread);
- });
- this.redraw();
- }
-
- publishSliceDetails(click: SliceDetails) {
- globals.sliceDetails = click;
- 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();
- }
-
- publishHeapProfileDetails(click: HeapProfileDetails) {
- globals.heapProfileDetails = click;
- this.redraw();
- }
-
- publishCpuProfileDetails(details: CpuProfileDetails) {
- globals.cpuProfileDetails = details;
- this.redraw();
- }
-
- publishHasFtrace(hasFtrace: boolean) {
- globals.hasFtrace = hasFtrace;
- this.redraw();
- }
-
- publishConversionJobStatusUpdate(job: ConversionJobStatusUpdate) {
- globals.setConversionJobStatus(job.jobName, job.jobStatus);
- this.redraw();
- }
-
- publishFileDownload(args: {file: File, name?: string}) {
- const url = URL.createObjectURL(args.file);
- const a = document.createElement('a');
- a.href = url;
- a.download = args.name !== undefined ? args.name : args.file.name;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- URL.revokeObjectURL(url);
- }
-
- publishLoading(numQueuedQueries: number) {
- globals.numQueuedQueries = numQueuedQueries;
- // TODO(hjd): Clean up loadingAnimation given that this now causes a full
- // redraw anyways. Also this should probably just go via the global state.
- globals.rafScheduler.scheduleFullRedraw();
- }
-
- // For opening JSON/HTML traces with the legacy catapult viewer.
- publishLegacyTrace(args: {data: ArrayBuffer, size: number}) {
- const arr = new Uint8Array(args.data, 0, args.size);
- const str = (new TextDecoder('utf-8')).decode(arr);
- openBufferWithLegacyTraceViewer('trace.json', str, 0);
- }
-
- publishBufferUsage(args: {percentage: number}) {
- globals.setBufferUsage(args.percentage);
- this.redraw();
- }
-
- publishSearch(args: SearchSummary) {
- globals.searchSummary = args;
- this.redraw();
- }
-
- publishSearchResult(args: CurrentSearchResults) {
- globals.currentSearchResults = args;
- this.redraw();
- }
-
- publishRecordingLog(args: {logs: string}) {
- globals.setRecordingLog(args.logs);
- this.redraw();
- }
-
- 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();
- }
-
- // This method is called by the controller via the Remote<> interface whenver
- // a new trace is loaded. This creates a new worker and passes it the
- // MessagePort received by the controller. This is because on Safari, all
- // workers must be spawned from the main thread.
- resetEngineWorker(port: MessagePort) {
- // We keep always an idle worker around, the first one is created by the
- // main() below, so we can hide the latency of the Wasm initialization.
- if (activeWasmWorker !== undefined) {
- activeWasmWorker.terminate();
- }
- // Swap the active worker with the idle one and create a new idle worker
- // for the next trace.
- activeWasmWorker = assertExists(idleWasmWorker);
- const msg: EngineWorkerInitMessage = {enginePort: port};
- activeWasmWorker.postMessage(msg, [port]);
- idleWasmWorker = new Worker(globals.root + 'engine_bundle.js');
- }
-
- private redraw(): void {
- if (globals.state.route &&
- globals.state.route !== this.router.getRouteFromHash()) {
- this.router.setRouteOnHash(globals.state.route);
- }
-
- globals.rafScheduler.scheduleFullRedraw();
- }
}
function setExtensionAvailability(available: boolean) {
@@ -380,9 +197,6 @@
window.addEventListener('error', e => reportError(e));
window.addEventListener('unhandledrejection', e => reportError(e));
- const controller = new Worker(globals.root + 'controller_bundle.js');
- idleWasmWorker = new Worker(globals.root + 'engine_bundle.js');
- const frontendChannel = new MessageChannel();
const controllerChannel = new MessageChannel();
const extensionLocalChannel = new MessageChannel();
const errorReportingChannel = new MessageChannel();
@@ -391,35 +205,38 @@
maybeShowErrorDialog(`${e.data}`);
const msg: ControllerWorkerInitMessage = {
- frontendPort: frontendChannel.port1,
controllerPort: controllerChannel.port1,
extensionPort: extensionLocalChannel.port1,
errorReportingPort: errorReportingChannel.port1,
};
- controller.postMessage(msg, [
- msg.frontendPort,
- msg.controllerPort,
- msg.extensionPort,
- msg.errorReportingPort,
- ]);
- const dispatch =
- controllerChannel.port2.postMessage.bind(controllerChannel.port2);
- globals.initialize(dispatch, controller);
+
+ initWasm(globals.root);
+ initializeImmerJs();
+
+ initController(msg);
+
+ const dispatch = (action: DeferredAction) => {
+ frontendApi.dispatchMultiple([action]);
+ };
+
+ const router = new Router({
+ '/': HomePage,
+ '/viewer': ViewerPage,
+ '/record': RecordPage,
+ '/query': AnalyzePage,
+ '/flags': FlagsPage,
+ '/metrics': MetricsPage,
+ '/info': TraceInfoPage,
+ });
+ router.onRouteChanged = (route) => {
+ globals.rafScheduler.scheduleFullRedraw();
+ maybeOpenTraceFromRoute(route);
+ };
+ globals.initialize(dispatch, router);
globals.serviceWorkerController.install();
- const router = new Router(
- '/',
- {
- '/': HomePage,
- '/viewer': ViewerPage,
- '/record': RecordPage,
- '/query': AnalyzePage,
- '/metrics': MetricsPage,
- '/info': TraceInfoPage,
- },
- dispatch,
- globals.logging);
- forwardRemoteCalls(frontendChannel.port2, new FrontendApi(router));
+ const frontendApi = new FrontendApi(controllerChannel.port2);
+ globals.publishRedraw = () => globals.rafScheduler.scheduleFullRedraw();
// We proxy messages between the extension and the controller because the
// controller's worker can't access chrome.runtime.
@@ -438,6 +255,10 @@
// This forwards the messages from the extension to the controller.
extensionPort.onMessage.addListener(
(message: object, _port: chrome.runtime.Port) => {
+ if (isGetCategoriesResponse(message)) {
+ globals.dispatch(Actions.setChromeCategories(message));
+ return;
+ }
extensionLocalChannel.port2.postMessage(message);
});
}
@@ -457,63 +278,23 @@
if (e.ctrlKey) e.preventDefault();
}, {passive: false});
- cssLoadPromise.then(() => onCssLoaded(router));
+ cssLoadPromise.then(() => onCssLoaded());
+
+ if (globals.testing) {
+ document.body.classList.add('testing');
+ }
}
-function onCssLoaded(router: Router) {
+
+function onCssLoaded() {
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);
- });
- }
+ globals.rafScheduler.domRedraw = () => {
+ m.render(main, globals.router.resolve());
+ };
// Add support for opening traces from postMessage().
window.addEventListener('message', postMessageHandler, {passive: true});
@@ -534,6 +315,9 @@
console.error('WebUSB API not supported');
}
installFileDropHandler();
+
+ // Handles the initial ?trace_id=a0b1c2 or ?s=permalink or ?url=... cases.
+ maybeOpenTraceFromRoute(Router.parseUrl(window.location.href));
}
main();
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index 7d82ac2..cb94e2b 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -13,6 +13,8 @@
// limitations under the License.
import {Actions} from '../common/actions';
+import {featureFlags} from '../common/feature_flags';
+import {DEFAULT_PIVOT_TABLE_ID} from '../common/pivot_table_common';
import {Area} from '../common/state';
import {Flow, globals} from './globals';
@@ -24,6 +26,13 @@
} from './scroll_helper';
import {executeSearch} from './search_handler';
+export const PIVOT_TABLE_FLAG = featureFlags.register({
+ id: 'pivotTables',
+ name: 'Pivot tables',
+ description: 'Show experimental pivot table details tab.',
+ defaultValue: false,
+});
+
const INSTANT_FOCUS_DURATION_S = 1 / 1e9; // 1 ns.
type Direction = 'Forward'|'Backward';
@@ -42,22 +51,8 @@
if (down && 'f' === key) {
findCurrentSelection();
}
- if (down && 'v' === key) {
- globals.dispatch(Actions.toggleVideo({}));
- }
- if (down && 'p' === key) {
- globals.dispatch(Actions.toggleFlagPause({}));
- }
- if (down && 't' === key) {
- globals.dispatch(Actions.toggleScrubbing({}));
- if (globals.frontendLocalState.vidTimestamp < 0) {
- globals.frontendLocalState.setVidTimestamp(Number.MAX_SAFE_INTEGER);
- } else {
- globals.frontendLocalState.setVidTimestamp(Number.MIN_SAFE_INTEGER);
- }
- }
if (down && 'b' === key && (e.ctrlKey || e.metaKey)) {
- globals.frontendLocalState.toggleSidebar();
+ globals.dispatch(Actions.toggleSidebar({}));
}
if (down && '?' === key) {
toggleHelp();
@@ -85,6 +80,19 @@
moveByFocusedFlow('Backward');
}
}
+ if (down && 'p' === key && !e.ctrlKey && PIVOT_TABLE_FLAG.get()) {
+ e.preventDefault();
+ globals.frontendLocalState.togglePivotTable();
+ const pivotTableId = DEFAULT_PIVOT_TABLE_ID;
+ if (globals.state.pivotTable[pivotTableId] === undefined) {
+ globals.dispatch(Actions.addNewPivotTable({
+ name: 'Pivot Table',
+ pivotTableId,
+ selectedPivots: [],
+ selectedAggregations: []
+ }));
+ }
+ }
}
// Search |boundFlows| for |flowId| and return the id following it.
@@ -125,13 +133,13 @@
flow.end.sliceId === sliceId && direction === 'Backward');
if (direction === 'Backward') {
- const nextFlowId = findAnotherFlowExcept(
- boundFlows, globals.frontendLocalState.focusedFlowIdLeft);
- globals.frontendLocalState.setHighlightedFlowLeftId(nextFlowId);
+ const nextFlowId =
+ findAnotherFlowExcept(boundFlows, globals.state.focusedFlowIdLeft);
+ globals.dispatch(Actions.setHighlightedFlowLeftId({flowId: nextFlowId}));
} else {
- const nextFlowId = findAnotherFlowExcept(
- boundFlows, globals.frontendLocalState.focusedFlowIdRight);
- globals.frontendLocalState.setHighlightedFlowRightId(nextFlowId);
+ const nextFlowId =
+ findAnotherFlowExcept(boundFlows, globals.state.focusedFlowIdRight);
+ globals.dispatch(Actions.setHighlightedFlowRightId({flowId: nextFlowId}));
}
}
@@ -144,9 +152,8 @@
const sliceId = globals.state.currentSelection.id;
const flowId =
- (direction === 'Backward' ?
- globals.frontendLocalState.focusedFlowIdLeft :
- globals.frontendLocalState.focusedFlowIdRight);
+ (direction === 'Backward' ? globals.state.focusedFlowIdLeft :
+ globals.state.focusedFlowIdRight);
if (sliceId === -1 || flowId === -1) {
return;
@@ -165,31 +172,46 @@
}
}
-function findTimeRangeOfSelection() {
+function findTimeRangeOfSelection(): {startTs: number, endTs: number} {
const selection = globals.state.currentSelection;
let startTs = -1;
let endTs = -1;
- if (selection !== null) {
- if (selection.kind === 'SLICE' || selection.kind === 'CHROME_SLICE') {
- const slice = globals.sliceDetails;
- if (slice.ts && slice.dur !== undefined && slice.dur > 0) {
- 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;
- }
- } else if (selection.kind === 'COUNTER') {
- startTs = selection.leftTs;
- endTs = selection.rightTs;
+ if (selection === null) {
+ return {startTs, endTs};
+ } else if (selection.kind === 'SLICE' || selection.kind === 'CHROME_SLICE') {
+ const slice = globals.sliceDetails;
+ if (slice.ts && slice.dur !== undefined && slice.dur > 0) {
+ 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;
+ }
+ } else if (selection.kind === 'COUNTER') {
+ startTs = selection.leftTs;
+ endTs = selection.rightTs;
+ } else if (selection.kind === 'AREA') {
+ const selectedArea = globals.state.areas[selection.areaId];
+ if (selectedArea) {
+ startTs = selectedArea.startSec;
+ endTs = selectedArea.endSec;
+ }
+ } else if (selection.kind === 'NOTE') {
+ const selectedNote = globals.state.notes[selection.id];
+ // Notes can either be default or area notes. Area notes are handled
+ // above in the AREA case.
+ if (selectedNote && selectedNote.noteType === 'DEFAULT') {
+ startTs = selectedNote.timestamp;
+ endTs = selectedNote.timestamp + INSTANT_FOCUS_DURATION_S;
}
}
+
return {startTs, endTs};
}
diff --git a/ui/src/frontend/logs_panel.ts b/ui/src/frontend/logs_panel.ts
index 3087935..2a1c664 100644
--- a/ui/src/frontend/logs_panel.ts
+++ b/ui/src/frontend/logs_panel.ts
@@ -81,11 +81,11 @@
}
onRowOver(ts: number) {
- globals.frontendLocalState.setHoveredLogsTimestamp(ts);
+ globals.dispatch(Actions.setHoveredLogsTimestamp({ts}));
}
onRowOut() {
- globals.frontendLocalState.setHoveredLogsTimestamp(-1);
+ globals.dispatch(Actions.setHoveredLogsTimestamp({ts: -1}));
}
private totalRows():
diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts
index 55dc47a..2ce959a 100644
--- a/ui/src/frontend/notes_panel.ts
+++ b/ui/src/frontend/notes_panel.ts
@@ -27,9 +27,7 @@
const FLAG_WIDTH = 16;
const AREA_TRIANGLE_WIDTH = 10;
-const MOVIE_WIDTH = 16;
const FLAG = `\uE153`;
-const MOVIE = '\uE8DA';
function toSummary(s: string) {
const newlineIndex = s.indexOf('\n') > 0 ? s.indexOf('\n') : s.length;
@@ -50,11 +48,6 @@
oncreate({dom}: m.CVnodeDOM) {
dom.addEventListener('mousemove', (e: Event) => {
this.hoveredX = (e as PerfettoMouseEvent).layerX - TRACK_SHELL_WIDTH;
- if (globals.state.scrubbingEnabled) {
- const timescale = globals.frontendLocalState.timeScale;
- const timestamp = timescale.pxToTime(this.hoveredX);
- globals.frontendLocalState.setVidTimestamp(timestamp);
- }
globals.rafScheduler.scheduleRedraw();
}, {passive: true});
dom.addEventListener('mouseenter', (e: Event) => {
@@ -63,16 +56,14 @@
});
dom.addEventListener('mouseout', () => {
this.hoveredX = null;
- globals.frontendLocalState.setHoveredNoteTimestamp(-1);
- globals.rafScheduler.scheduleRedraw();
+ globals.dispatch(Actions.setHoveredNoteTimestamp({ts: -1}));
}, {passive: true});
}
view() {
return m('.notes-panel', {
onclick: (e: PerfettoMouseEvent) => {
- const isMovie = globals.state.flagPauseEnabled;
- this.onClick(e.layerX - TRACK_SHELL_WIDTH, e.layerY, isMovie);
+ this.onClick(e.layerX - TRACK_SHELL_WIDTH, e.layerY);
e.stopPropagation();
},
});
@@ -124,8 +115,7 @@
note.color,
isSelected);
} else {
- this.drawFlag(
- ctx, left, size.height, note.color, note.noteType, isSelected);
+ this.drawFlag(ctx, left, size.height, note.color, isSelected);
}
if (note.text) {
@@ -142,17 +132,18 @@
// A real note is hovered so we don't need to see the preview line.
// TODO(hjd): Change cursor to pointer here.
- if (aNoteIsHovered) globals.frontendLocalState.setHoveredNoteTimestamp(-1);
+ if (aNoteIsHovered) {
+ globals.dispatch(Actions.setHoveredNoteTimestamp({ts: -1}));
+ }
// View preview note flag when hovering on notes panel.
if (!aNoteIsHovered && this.hoveredX !== null) {
const timestamp = timeScale.pxToTime(this.hoveredX);
if (timeScale.timeInBounds(timestamp)) {
- globals.frontendLocalState.setHoveredNoteTimestamp(timestamp);
+ globals.dispatch(Actions.setHoveredNoteTimestamp({ts: timestamp}));
const x = timeScale.timeToPx(timestamp);
const left = Math.floor(x + TRACK_SHELL_WIDTH);
- this.drawFlag(
- ctx, left, size.height, '#aaa', 'DEFAULT', /* fill */ true);
+ this.drawFlag(ctx, left, size.height, '#aaa', /* fill */ true);
}
}
}
@@ -194,7 +185,7 @@
private drawFlag(
ctx: CanvasRenderingContext2D, x: number, height: number, color: string,
- noteType: 'DEFAULT'|'AREA'|'MOVIE', fill?: boolean) {
+ fill?: boolean) {
const prevFont = ctx.font;
const prevBaseline = ctx.textBaseline;
ctx.textBaseline = 'alphabetic';
@@ -206,26 +197,21 @@
// exactly at the x value. This adjusts for that.
const iconPadding = 6;
if (fill) {
- ctx.fillText(
- noteType === 'MOVIE' ? MOVIE : FLAG, x - iconPadding, height + 2);
+ ctx.fillText(FLAG, x - iconPadding, height + 2);
} else {
- ctx.strokeText(
- noteType === 'MOVIE' ? MOVIE : FLAG, x - iconPadding, height + 2.5);
+ ctx.strokeText(FLAG, x - iconPadding, height + 2.5);
}
ctx.font = prevFont;
ctx.textBaseline = prevBaseline;
}
- private onClick(x: number, _: number, isMovie: boolean) {
+ private onClick(x: number, _: number) {
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);
- }
if (note.noteType === 'AREA') {
globals.makeSelection(
Actions.reSelectArea({areaId: note.areaId, noteId: note.id}));
@@ -235,11 +221,8 @@
return;
}
}
- if (isMovie) {
- globals.frontendLocalState.setVidTimestamp(timestamp);
- }
const color = randomColor();
- globals.makeSelection(Actions.addNote({timestamp, color, isMovie}));
+ globals.makeSelection(Actions.addNote({timestamp, color}));
}
private mouseOverNote(x: number, note: AreaNote|Note): boolean {
@@ -251,7 +234,7 @@
(timeScale.timeToPx(noteArea.endSec) > x &&
x > timeScale.timeToPx(noteArea.endSec) - AREA_TRIANGLE_WIDTH);
} else {
- const width = (note.noteType === 'MOVIE') ? MOVIE_WIDTH : FLAG_WIDTH;
+ const width = FLAG_WIDTH;
return noteX <= x && x < noteX + width;
}
}
@@ -298,7 +281,7 @@
{
onclick: () => {
globals.dispatch(Actions.removeNote({id: attrs.id}));
- globals.frontendLocalState.currentTab = undefined;
+ globals.dispatch(Actions.setCurrentTab({tab: undefined}));
globals.rafScheduler.scheduleFullRedraw();
}
},
diff --git a/ui/src/frontend/pages.ts b/ui/src/frontend/pages.ts
index c595420..6d5448b 100644
--- a/ui/src/frontend/pages.ts
+++ b/ui/src/frontend/pages.ts
@@ -16,6 +16,7 @@
import {Actions} from '../common/actions';
+import {onClickCopy} from './clipboard';
import {CookieConsent} from './cookie_consent';
import {globals} from './globals';
import {Sidebar} from './sidebar';
@@ -25,9 +26,10 @@
const permalink = globals.state.permalink;
if (!permalink.requestId || !permalink.hash) return null;
const url = `${self.location.origin}/#!/?s=${permalink.hash}`;
+ const linkProps = {title: 'Click to copy the URL', onclick: onClickCopy(url)};
return m('.alert-permalink', [
- m('div', 'Permalink: ', m(`a[href=${url}]`, url)),
+ m('div', 'Permalink: ', m(`a[href=${url}]`, linkProps, url)),
m('button',
{
onclick: () => globals.dispatch(Actions.clearPermalink({})),
@@ -45,17 +47,18 @@
/**
* Wrap component with common UI elements (nav bar etc).
*/
-export function createPage(component: m.Component): m.Component {
+export function createPage(component: m.Component<PageAttrs>):
+ m.Component<PageAttrs> {
const pageComponent = {
- view() {
+ view({attrs}: m.Vnode<PageAttrs>) {
const children = [
m(Sidebar),
m(Topbar),
m(Alerts),
- m(component),
+ m(component, attrs),
m(CookieConsent),
];
- if (globals.frontendLocalState.perfDebug) {
+ if (globals.state.perfDebug) {
children.push(m('.perf-stats'));
}
return children;
@@ -64,3 +67,7 @@
return pageComponent;
}
+
+export interface PageAttrs {
+ subpage?: string;
+}
diff --git a/ui/src/frontend/pan_and_zoom_handler.ts b/ui/src/frontend/pan_and_zoom_handler.ts
index 166a3ce..cbbb0ae 100644
--- a/ui/src/frontend/pan_and_zoom_handler.ts
+++ b/ui/src/frontend/pan_and_zoom_handler.ts
@@ -211,8 +211,7 @@
}
private onMouseMove(e: MouseEvent) {
- const pageOffset =
- globals.frontendLocalState.sidebarVisible ? this.contentOffsetX : 0;
+ const pageOffset = globals.state.sidebarVisible ? this.contentOffsetX : 0;
// We can't use layerX here because there are many layers in this element.
this.mousePositionX = e.clientX - pageOffset;
// Only change the cursor when hovering, the DragGestureHandler handles
diff --git a/ui/src/frontend/perf.ts b/ui/src/frontend/perf.ts
index 8ab8c4a..d884a5f 100644
--- a/ui/src/frontend/perf.ts
+++ b/ui/src/frontend/perf.ts
@@ -15,13 +15,14 @@
import * as m from 'mithril';
+import {Actions} from '../common/actions';
import {globals} from './globals';
import {PanelContainer} from './panel_container';
/**
* Shorthand for if globals perf debug mode is on.
*/
-export const perfDebug = () => globals.frontendLocalState.perfDebug;
+export const perfDebug = () => globals.state.perfDebug;
/**
* Returns performance.now() if perfDebug is enabled, otherwise 0.
@@ -113,7 +114,7 @@
m('section', globals.rafScheduler.renderPerfStats()),
m('button.close-button',
{
- onclick: () => globals.frontendLocalState.togglePerfDebug(),
+ onclick: () => globals.dispatch(Actions.togglePerfDebug({})),
},
m('i.material-icons', 'close')),
this.containers.map((c, i) => m('section', c.renderPerfStats(i)))
diff --git a/ui/src/frontend/pivot_table.ts b/ui/src/frontend/pivot_table.ts
new file mode 100644
index 0000000..70e87ae
--- /dev/null
+++ b/ui/src/frontend/pivot_table.ts
@@ -0,0 +1,332 @@
+// 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 * as m from 'mithril';
+
+import {Actions} from '../common/actions';
+import {
+ ColumnAttrs,
+ PivotTableQueryResponse,
+ RowAttrs,
+} from '../common/pivot_table_common';
+
+import {globals} from './globals';
+import {Panel} from './panel';
+import {
+ PivotTableHelper,
+} from './pivot_table_helper';
+
+interface ExpandableCellAttrs {
+ pivotTableId: string;
+ row: RowAttrs;
+ column: ColumnAttrs;
+ rowIndices: number[];
+ expandedRowColumns: string[];
+}
+
+interface PivotTableRowAttrs {
+ pivotTableId: string;
+ row: RowAttrs;
+ columns: ColumnAttrs[];
+ rowIndices: number[];
+ expandedRowColumns: string[];
+}
+
+interface PivotTableBodyAttrs {
+ pivotTableId: string;
+ rows: RowAttrs[];
+ columns: ColumnAttrs[];
+ rowIndices: number[];
+ expandedRowColumns: string[];
+}
+
+interface PivotTableHeaderAttrs {
+ helper: PivotTableHelper;
+}
+
+interface PivotTableAttrs {
+ pivotTableId: string;
+ helper?: PivotTableHelper;
+}
+
+class PivotTableHeader implements m.ClassComponent<PivotTableHeaderAttrs> {
+ view(vnode: m.Vnode<PivotTableHeaderAttrs>) {
+ const {helper} = vnode.attrs;
+ const pivotTableId = helper.pivotTableId;
+ const pivotTable = globals.state.pivotTable[pivotTableId];
+ const resp =
+ globals.queryResults.get(pivotTableId) as PivotTableQueryResponse;
+
+ const cols = [];
+ for (const column of resp.columns) {
+ const isPivot = column.aggregation === undefined;
+ let sortIcon;
+ if (!isPivot) {
+ sortIcon =
+ column.order === 'DESC' ? 'arrow_drop_down' : 'arrow_drop_up';
+ }
+ cols.push(m(
+ 'td',
+ {
+ class: pivotTable.isLoadingQuery ? 'disabled' : '',
+ draggable: pivotTable.isLoadingQuery ? false : true,
+ ondragstart: (e: DragEvent) => {
+ helper.selectedColumnOnDrag(e, isPivot, column.index);
+ },
+ ondrop: (e: DragEvent) => {
+ helper.removeHighlightFromDropLocation(e);
+ helper.selectedColumnOnDrop(e, isPivot, column.index);
+ helper.queryPivotTableChanges();
+ },
+ ondragenter: (e: DragEvent) => {
+ helper.highlightDropLocation(e, isPivot);
+ },
+ ondragleave: (e: DragEvent) => {
+ helper.removeHighlightFromDropLocation(e);
+ }
+ },
+ column.name,
+ (!isPivot && sortIcon !== undefined ?
+ m('i.material-icons',
+ {
+ onclick: () => {
+ if (!pivotTable.isLoadingQuery) {
+ helper.togglePivotTableAggregationSorting(column.index);
+ helper.queryPivotTableChanges();
+ }
+ }
+ },
+ sortIcon) :
+ null),
+ (!isPivot && resp.totalAggregations !== undefined ?
+ m('.total-aggregation',
+ `(${resp.totalAggregations[column.name]})`) :
+ null)));
+ }
+ return m('tr', cols);
+ }
+}
+
+class ExpandableCell implements m.ClassComponent<ExpandableCellAttrs> {
+ view(vnode: m.Vnode<ExpandableCellAttrs>) {
+ const {pivotTableId, row, column, rowIndices, expandedRowColumns} =
+ vnode.attrs;
+ const pivotTable = globals.state.pivotTable[pivotTableId];
+ let expandIcon = 'expand_more';
+ if (row.expandedRows.has(column.name)) {
+ expandIcon = row.expandedRows.get(column.name)!.isExpanded ?
+ 'expand_less' :
+ 'expand_more';
+ }
+ let spinnerVsibility = 'hidden';
+ let animationState = 'paused';
+ if (row.loadingColumn === column.name) {
+ spinnerVsibility = 'visible';
+ animationState = 'running';
+ }
+ const padValue = new Array(row.depth * 2).join(' ');
+
+ return m(
+ 'td.allow-white-space',
+ padValue,
+ m('i.material-icons',
+ {
+ class: pivotTable.isLoadingQuery ? 'disabled' : '',
+ onclick: () => {
+ if (pivotTable.isLoadingQuery) {
+ return;
+ }
+ const value = row.row[column.name]?.toString();
+ if (value === undefined) {
+ throw Error('Expanded row has undefined value.');
+ }
+ if (row.expandedRows.has(column.name) &&
+ row.expandedRows.get(column.name)!.isExpanded) {
+ globals.dispatch(Actions.setPivotTableRequest({
+ pivotTableId,
+ action: 'UNEXPAND',
+ attrs: {
+ rowIndices,
+ columnIdx: column.index,
+ value,
+ expandedRowColumns
+ }
+ }));
+ } else {
+ globals.dispatch(Actions.setPivotTableRequest({
+ pivotTableId,
+ action: column.isStackColumn ? 'DESCENDANTS' : 'EXPAND',
+ attrs: {
+ rowIndices,
+ columnIdx: column.index,
+ value,
+ expandedRowColumns
+ }
+ }));
+ }
+ },
+ },
+ expandIcon),
+ ' ',
+ row.row[column.name],
+ ' ',
+ // Adds a loading spinner while querying the expanded column.
+ m('.pivot-table-spinner', {
+ style:
+ {visibility: spinnerVsibility, animationPlayState: animationState}
+ }));
+ }
+}
+
+class PivotTableRow implements m.ClassComponent<PivotTableRowAttrs> {
+ view(vnode: m.Vnode<PivotTableRowAttrs>) {
+ const cells = [];
+ const {pivotTableId, row, columns, rowIndices, expandedRowColumns} =
+ vnode.attrs;
+
+ for (const column of columns) {
+ if (row.row[column.name] === undefined &&
+ row.expandableColumns.has(column.name)) {
+ throw Error(
+ `Row data at expandable column "${column.name}" is undefined.`);
+ }
+ if (row.row[column.name] === undefined || row.row[column.name] === null) {
+ cells.push(m('td', ''));
+ continue;
+ }
+ if (row.expandableColumns.has(column.name)) {
+ cells.push(
+ m(ExpandableCell,
+ {pivotTableId, row, column, rowIndices, expandedRowColumns}));
+ continue;
+ }
+ let indentationLevel = 0;
+ let expandIconSpace = 0;
+ if (column.aggregation !== undefined) {
+ indentationLevel = rowIndices.length - 1;
+ } else {
+ indentationLevel = row.depth;
+ if (row.depth > 0 && column.isStackColumn) {
+ expandIconSpace = 3;
+ }
+ }
+ // For each indentation level add 2 spaces, if we have an expansion button
+ // add 3 spaces to cover the icon size.
+ let value = row.row[column.name]!.toString();
+ value = value.padStart(
+ (indentationLevel * 2) + expandIconSpace + value.length, ' ');
+ cells.push(m('td.allow-white-space', value));
+ }
+ return m('tr', cells);
+ }
+}
+
+class PivotTableBody implements m.ClassComponent<PivotTableBodyAttrs> {
+ view(vnode: m.Vnode<PivotTableBodyAttrs>): m.Children {
+ const pivotTableRows = [];
+ const {pivotTableId, rows, columns, rowIndices, expandedRowColumns} =
+ vnode.attrs;
+ for (let i = 0; i < rows.length; ++i) {
+ pivotTableRows.push(m(PivotTableRow, {
+ pivotTableId,
+ row: rows[i],
+ columns,
+ rowIndices: rowIndices.concat(i),
+ expandedRowColumns
+ }));
+ for (const column of columns.slice().reverse()) {
+ const expandedRows = rows[i].expandedRows.get(column.name);
+ if (expandedRows !== undefined && expandedRows.isExpanded) {
+ pivotTableRows.push(m(PivotTableBody, {
+ pivotTableId,
+ rows: expandedRows.rows,
+ columns,
+ rowIndices: rowIndices.concat(i),
+ expandedRowColumns: expandedRowColumns.concat(column.name)
+ }));
+ }
+ }
+ }
+ return pivotTableRows;
+ }
+}
+
+export class PivotTable extends Panel<PivotTableAttrs> {
+ view(vnode: m.CVnode<PivotTableAttrs>) {
+ const {pivotTableId, helper} = vnode.attrs;
+ const pivotTable = globals.state.pivotTable[pivotTableId];
+ const resp =
+ globals.queryResults.get(pivotTableId) as PivotTableQueryResponse;
+
+ let body;
+ let header;
+ if (helper !== undefined && resp !== undefined) {
+ header = m(PivotTableHeader, {helper});
+ body = m(PivotTableBody, {
+ pivotTableId,
+ rows: resp.rows,
+ columns: resp.columns,
+ rowIndices: [],
+ expandedRowColumns: []
+ });
+ }
+
+ const startSec = pivotTable.traceTime ? pivotTable.traceTime.startSec :
+ globals.state.traceTime.startSec;
+ const endSec = pivotTable.traceTime ? pivotTable.traceTime.endSec :
+ globals.state.traceTime.endSec;
+
+ return m(
+ 'div.pivot-table-tab',
+ m(
+ 'header.overview',
+ m('span',
+ m('button',
+ {
+ disabled: helper === undefined || pivotTable.isLoadingQuery,
+ onclick: () => {
+ if (helper !== undefined) {
+ helper.toggleEditPivotTableModal();
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ }
+ },
+ 'Edit'),
+ ' ',
+ (pivotTable.isLoadingQuery ? m('.pivot-table-spinner') : null),
+ (resp !== undefined && !pivotTable.isLoadingQuery ?
+ m('span.code',
+ `Query took ${Math.round(resp.durationMs)} ms -`) :
+ null),
+ m('span.code', `Selected range: ${endSec - startSec} s`)),
+ m('button',
+ {
+ disabled: helper === undefined || pivotTable.isLoadingQuery,
+ onclick: () => {
+ globals.frontendLocalState.togglePivotTable();
+ globals.queryResults.delete(pivotTableId);
+ globals.pivotTableHelper.delete(pivotTableId);
+ globals.dispatch(Actions.deletePivotTable({pivotTableId}));
+ }
+ },
+ 'Close'),
+ ),
+ m('.query-table-container',
+ m('table.query-table.pivot-table',
+ m('thead', header),
+ m('tbody', body))));
+ }
+
+ renderCanvas() {}
+}
diff --git a/ui/src/frontend/pivot_table_editor.ts b/ui/src/frontend/pivot_table_editor.ts
new file mode 100644
index 0000000..64a8c67
--- /dev/null
+++ b/ui/src/frontend/pivot_table_editor.ts
@@ -0,0 +1,251 @@
+// 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 * as m from 'mithril';
+import {isStackPivot} from '../common/pivot_table_common';
+
+import {globals} from './globals';
+import {hideModel} from './modal';
+import {
+ PivotTableHelper,
+} from './pivot_table_helper';
+
+interface PivotTableEditorAttrs {
+ helper: PivotTableHelper;
+}
+
+export class ColumnPicker implements m.ClassComponent<PivotTableEditorAttrs> {
+ view(vnode: m.Vnode<PivotTableEditorAttrs>) {
+ const {helper} = vnode.attrs;
+
+ // Fills available aggregations options in aggregation select.
+ const aggregationOptions = [];
+ for (const aggregation of helper.availableAggregations) {
+ aggregationOptions.push(
+ m('option', {value: aggregation, key: aggregation}, aggregation));
+ }
+
+ // Fills available columns options divided according to their table in
+ // column select.
+ const columnOptionGroup = [];
+ for (const {tableName, columns} of helper.availableColumns) {
+ const options = [];
+ for (const column of columns) {
+ // We can't aggregate a stack column.
+ const hidden = !helper.isPivot && isStackPivot(tableName, column);
+ options.push(m('option', {value: column, key: column, hidden}, column));
+ }
+ columnOptionGroup.push(m('optgroup', {label: tableName}, options));
+ }
+
+ return m(
+ 'div',
+ m(
+ 'section',
+ m('h2', 'Select column type: '),
+ // Pivot radio button.
+ m(
+ 'span',
+ m(`input[type=radio][name=type][id=pivot]`, {
+ checked: helper.isPivot,
+ onchange: () => {
+ helper.togglePivotSelection();
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ }),
+ m(`label[for=pivot]`, 'Pivot'),
+ ),
+ // Aggregation radio button.
+ m('span', m(`input[type=radio][name=type][id=aggregation]`, {
+ checked: !helper.isPivot,
+ onchange: () => {
+ helper.togglePivotSelection();
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ })),
+ m(`label[for=aggregation]`, 'Aggregation'),
+ ),
+ m(
+ 'section',
+ m('h2', 'Select a column: '),
+ // Aggregation select.
+ m('select',
+ {
+ disabled: helper.isPivot,
+ selectedIndex: helper.selectedAggregationIndex,
+ onchange: (e: InputEvent) => {
+ helper.setSelectedPivotTableAggregationIndex(
+ (e.target as HTMLSelectElement).selectedIndex);
+ }
+ },
+ aggregationOptions),
+ ' ',
+ // Column select.
+ m('select',
+ {
+ selectedIndex: helper.selectedColumnIndex,
+ onchange: (e: InputEvent) => {
+ helper.setSelectedPivotTableColumnIndex(
+ (e.target as HTMLSelectElement).selectedIndex);
+ }
+ },
+ columnOptionGroup),
+ ),
+ m('section.button-group',
+ // Button to toggle selected column.
+ m('button',
+ {
+ onclick: () => {
+ helper.updatePivotTableColumnOnSelectedIndex();
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ },
+ 'Add/Remove'),
+ // Button to clear table and all selected columns.
+ m('button',
+ {
+ onclick: () => {
+ helper.clearPivotTableColumns();
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ },
+ 'Clear')));
+ }
+}
+
+export class ColumnDisplay implements m.ClassComponent<PivotTableEditorAttrs> {
+ view(vnode: m.Vnode<PivotTableEditorAttrs>) {
+ const {helper} = vnode.attrs;
+ const selectedPivotsDisplay = [];
+ const selectedAggregationsDisplay = [];
+
+ for (let i = 0; i < helper.selectedPivots.length; ++i) {
+ const columnAttrs = helper.selectedPivots[i];
+ selectedPivotsDisplay.push(m(
+ 'tr',
+ m('td',
+ {
+ draggable: true,
+ ondragstart: (e: DragEvent) => {
+ helper.selectedColumnOnDrag(e, true, i);
+ },
+ ondrop: (e: DragEvent) => {
+ helper.removeHighlightFromDropLocation(e);
+ helper.selectedColumnOnDrop(e, true, i);
+ globals.rafScheduler.scheduleFullRedraw();
+ },
+ onclick: () => {
+ helper.selectPivotTableColumn(columnAttrs);
+ globals.rafScheduler.scheduleFullRedraw();
+ },
+ ondragenter: (e: DragEvent) => {
+ helper.highlightDropLocation(e, true);
+ },
+ ondragleave: (e: DragEvent) => {
+ helper.removeHighlightFromDropLocation(e);
+ }
+ },
+ m('i.material-icons',
+ {
+ onclick: () => {
+ helper.updatePivotTableColumnOnColumnAttributes(columnAttrs);
+ globals.rafScheduler.scheduleFullRedraw();
+ },
+ },
+ 'remove'),
+ ' ',
+ `${columnAttrs.tableName} ${columnAttrs.columnName}`)));
+ }
+
+ for (let i = 0; i < helper.selectedAggregations.length; ++i) {
+ const columnAttrs = helper.selectedAggregations[i];
+ const sortIcon = helper.selectedAggregations[i].order === 'DESC' ?
+ 'arrow_drop_down' :
+ 'arrow_drop_up';
+ selectedAggregationsDisplay.push(m(
+ 'tr',
+ m('td',
+ {
+ draggable: 'true',
+ ondragstart: (e: DragEvent) => {
+ helper.selectedColumnOnDrag(e, false, i);
+ },
+ ondrop: (e: DragEvent) => {
+ helper.removeHighlightFromDropLocation(e);
+ helper.selectedColumnOnDrop(e, false, i);
+ globals.rafScheduler.scheduleFullRedraw();
+ },
+ onclick: () => {
+ helper.selectPivotTableColumn(columnAttrs);
+ globals.rafScheduler.scheduleFullRedraw();
+ },
+ ondragenter: (e: DragEvent) => {
+ helper.highlightDropLocation(e, false);
+ },
+ ondragleave: (e: DragEvent) => {
+ helper.removeHighlightFromDropLocation(e);
+ }
+ },
+ m('i.material-icons',
+ {
+ onclick: () => {
+ helper.updatePivotTableColumnOnColumnAttributes(columnAttrs);
+ globals.rafScheduler.scheduleFullRedraw();
+ },
+ },
+ 'remove'),
+ ' ',
+ `${columnAttrs.tableName} ${columnAttrs.columnName} (${
+ columnAttrs.aggregation})`,
+ m('i.material-icons',
+ {
+ onclick: () => {
+ helper.togglePivotTableAggregationSorting(i);
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ },
+ sortIcon))));
+ }
+
+ return m(
+ 'div',
+ m('section.table-group',
+ // Table that displays selected pivots.
+ m('table',
+ m('thead', m('tr', m('th', 'Selected Pivots'))),
+ m('div.scroll', m('tbody', selectedPivotsDisplay))),
+ // Table that displays selected aggregations.
+ m('table',
+ m('thead', m('tr', m('th', 'Selected Aggregations'))),
+ m('div.scroll', m('tbody', selectedAggregationsDisplay)))),
+ m('section.button-group',
+ // Button to toggle selected column.
+ m('button',
+ {
+ onclick: () => {
+ helper.queryPivotTableChanges();
+ hideModel();
+ }
+ },
+ 'Query'),
+ // Button to clear table and all selected columns.
+ m('button',
+ {
+ onclick: () => {
+ hideModel();
+ }
+ },
+ 'Cancel')));
+ }
+}
diff --git a/ui/src/frontend/pivot_table_helper.ts b/ui/src/frontend/pivot_table_helper.ts
new file mode 100644
index 0000000..936a2d7
--- /dev/null
+++ b/ui/src/frontend/pivot_table_helper.ts
@@ -0,0 +1,355 @@
+// 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 {Actions} from '../common/actions';
+import {
+ AggregationAttrs,
+ isStackPivot,
+ PivotAttrs,
+ TableAttrs
+} from '../common/pivot_table_common';
+import {globals} from './globals';
+
+export function isAggregationAttrs(attrs: PivotAttrs|AggregationAttrs):
+ attrs is AggregationAttrs {
+ return (attrs as AggregationAttrs).aggregation !== undefined;
+}
+
+function equalTableAttrs(
+ left: PivotAttrs|AggregationAttrs, right: PivotAttrs|AggregationAttrs) {
+ if (left.columnName !== right.columnName) {
+ return false;
+ }
+
+ if (left.tableName !== right.tableName) {
+ return false;
+ }
+
+ if (isAggregationAttrs(left) && isAggregationAttrs(right)) {
+ if (left.aggregation !== right.aggregation) {
+ return false;
+ }
+ }
+ return true;
+}
+
+export function getDataTransferType(isPivot: boolean) {
+ if (isPivot) {
+ return 'perfetto/pivot-table-dragged-pivot';
+ }
+ return 'perfetto/pivot-table-dragged-aggregation';
+}
+
+export class PivotTableHelper {
+ readonly pivotTableId: string;
+ readonly availableColumns: TableAttrs[];
+ readonly availableAggregations: string[];
+ readonly totalColumnsCount = 0;
+
+ private _selectedPivots: PivotAttrs[] = [];
+ private _selectedAggregations: AggregationAttrs[] = [];
+ private _isPivot = true;
+ private _selectedColumnIndex = 0;
+ private _selectedAggregationIndex = 0;
+ private _editPivotTableModalOpen = false;
+
+ constructor(
+ pivotTableId: string, availableColumns: TableAttrs[],
+ availableAggregations: string[], selectedPivots: PivotAttrs[],
+ selectedAggregations: AggregationAttrs[]) {
+ this.pivotTableId = pivotTableId;
+ this.availableColumns = availableColumns;
+ for (const table of this.availableColumns) {
+ this.totalColumnsCount += table.columns.length;
+ }
+ this.availableAggregations = availableAggregations;
+ this.setSelectedPivotsAndAggregations(selectedPivots, selectedAggregations);
+ }
+
+ // Sets selected pivots and aggregations if the editor modal is not open.
+ setSelectedPivotsAndAggregations(
+ selectedPivots: PivotAttrs[], selectedAggregations: AggregationAttrs[]) {
+ if (!this.editPivotTableModalOpen) {
+ // Making a copy of selectedPivots and selectedAggregations to preserve
+ // the original state.
+ this._selectedPivots =
+ selectedPivots.map(pivot => Object.assign({}, pivot));
+ this._selectedAggregations = selectedAggregations.map(
+ aggregation => Object.assign({}, aggregation));
+ }
+ }
+
+ // Dictates if the selected indexes refer to a pivot or aggregation.
+ togglePivotSelection() {
+ this._isPivot = !this._isPivot;
+ if (this._isPivot === false) {
+ const selectedColumn = this.getSelectedPivotTableColumnAttrs();
+ if (isStackPivot(selectedColumn.tableName, selectedColumn.columnName)) {
+ this._selectedColumnIndex = Math.max(0, this._selectedColumnIndex - 1);
+ }
+ }
+ }
+
+ setSelectedPivotTableColumnIndex(index: number) {
+ if (index < 0 && index >= this.totalColumnsCount) {
+ throw Error(`Selected column index "${index}" out of bounds.`);
+ }
+ this._selectedColumnIndex = index;
+ }
+
+ setSelectedPivotTableAggregationIndex(index: number) {
+ if (index < 0 && index >= this.availableAggregations.length) {
+ throw Error(`Selected aggregation index "${index}" out of bounds.`);
+ }
+ this._selectedAggregationIndex = index;
+ }
+
+ // Get column attributes on selectedColumnIndex and
+ // selectedAggregationIndex.
+ getSelectedPivotTableColumnAttrs(): PivotAttrs|AggregationAttrs {
+ let tableName, columnName;
+ // Finds column index relative to its table.
+ let colIdx = this._selectedColumnIndex;
+ for (const {tableName: tblName, columns} of this.availableColumns) {
+ if (colIdx < columns.length) {
+ tableName = tblName;
+ columnName = columns[colIdx];
+ break;
+ }
+ colIdx -= columns.length;
+ }
+ if (tableName === undefined || columnName === undefined) {
+ throw Error(
+ 'Pivot table selected column does not exist in availableColumns.');
+ }
+
+ // Get aggregation if selected column is not a pivot, undefined otherwise.
+ if (!this._isPivot) {
+ const aggregation =
+ this.availableAggregations[this._selectedAggregationIndex];
+ return {tableName, columnName, aggregation, order: 'DESC'};
+ }
+
+ return {
+ tableName,
+ columnName,
+ isStackPivot: isStackPivot(tableName, columnName)
+ };
+ }
+
+ // Adds column based on selected index to selectedPivots or
+ // selectedAggregations if it doesn't already exist, remove otherwise.
+ updatePivotTableColumnOnSelectedIndex() {
+ const columnAttrs = this.getSelectedPivotTableColumnAttrs();
+ this.updatePivotTableColumnOnColumnAttributes(columnAttrs);
+ }
+
+ // Adds column based on column attributes to selectedPivots or
+ // selectedAggregations if it doesn't already exist, remove otherwise.
+ updatePivotTableColumnOnColumnAttributes(columnAttrs: PivotAttrs|
+ AggregationAttrs) {
+ let storage: Array<PivotAttrs|AggregationAttrs>;
+ let attrs: PivotAttrs|AggregationAttrs;
+ if (isAggregationAttrs(columnAttrs)) {
+ if (isStackPivot(columnAttrs.tableName, columnAttrs.columnName)) {
+ throw Error(
+ `Stack column "${columnAttrs.tableName} ${
+ columnAttrs.columnName}" should not ` +
+ `be added as an aggregation.`);
+ }
+ storage = this._selectedAggregations;
+ attrs = {
+ tableName: columnAttrs.tableName,
+ columnName: columnAttrs.columnName,
+ aggregation: columnAttrs.aggregation,
+ order: columnAttrs.order
+ };
+ } else {
+ storage = this._selectedPivots;
+ attrs = {
+ tableName: columnAttrs.tableName,
+ columnName: columnAttrs.columnName,
+ isStackPivot: columnAttrs.isStackPivot
+ };
+ }
+ const index =
+ storage.findIndex(element => equalTableAttrs(element, columnAttrs));
+
+ if (index === -1) {
+ storage.push(attrs);
+ } else {
+ storage.splice(index, 1);
+ }
+ }
+
+ clearPivotTableColumns() {
+ this._selectedPivots = [];
+ this._selectedAggregations = [];
+ }
+
+ // Changes aggregation sorting from DESC to ASC and vice versa.
+ togglePivotTableAggregationSorting(index: number) {
+ if (index < 0 || index >= this._selectedAggregations.length) {
+ throw Error(`Column index "${index}" is out of bounds.`);
+ }
+ this._selectedAggregations[index].order =
+ this._selectedAggregations[index].order === 'DESC' ? 'ASC' : 'DESC';
+ }
+
+ // Moves target column to the requested destination.
+ reorderPivotTableDraggedColumn(
+ isPivot: boolean, targetColumnIdx: number, destinationColumnIdx: number) {
+ let storage: Array<PivotAttrs|AggregationAttrs>;
+ if (isPivot) {
+ storage = this._selectedPivots;
+ } else {
+ storage = this._selectedAggregations;
+ }
+
+ if (targetColumnIdx < 0 || targetColumnIdx >= storage.length) {
+ throw Error(`Target column index "${targetColumnIdx}" out of bounds.`);
+ }
+ if (destinationColumnIdx < 0 || destinationColumnIdx >= storage.length) {
+ throw Error(
+ `Destination column index "${destinationColumnIdx}" out of bounds.`);
+ }
+
+ const targetColumn: PivotAttrs|AggregationAttrs = storage[targetColumnIdx];
+ storage.splice(targetColumnIdx, 1);
+ storage.splice(destinationColumnIdx, 0, targetColumn);
+ }
+
+ selectedColumnOnDrag(e: DragEvent, isPivot: boolean, targetIdx: number) {
+ const dataTransferType = getDataTransferType(isPivot);
+ if (e.dataTransfer === null) {
+ return;
+ }
+ e.dataTransfer.setData(dataTransferType, targetIdx.toString());
+ }
+
+ selectedColumnOnDrop(
+ e: DragEvent, isPivot: boolean, destinationColumnIdx: number) {
+ const dataTransferType = getDataTransferType(isPivot);
+ if (e.dataTransfer === null) {
+ return;
+ }
+ // Prevents dragging pivots to aggregations and vice versa.
+ if (!e.dataTransfer.types.includes(dataTransferType)) {
+ return;
+ }
+
+ const targetColumnIdxString = e.dataTransfer.getData(dataTransferType);
+ const targetColumnIdx = Number(targetColumnIdxString);
+ if (!Number.isInteger(targetColumnIdx)) {
+ throw Error(
+ `Target column index "${targetColumnIdxString}" is not valid.`);
+ }
+
+ this.reorderPivotTableDraggedColumn(
+ isPivot, targetColumnIdx, destinationColumnIdx);
+ e.dataTransfer.clearData(dataTransferType);
+ }
+
+
+ // Highlights valid drop locations when dragging over them.
+ highlightDropLocation(e: DragEvent, isPivot: boolean) {
+ if (e.dataTransfer === null) {
+ return;
+ }
+ // Prevents highlighting aggregations when dragging pivots over them
+ // and vice versa.
+ if (!e.dataTransfer.types.includes(getDataTransferType(isPivot))) {
+ return;
+ }
+ (e.target as HTMLTableDataCellElement).classList.add('drop-location');
+ }
+
+ removeHighlightFromDropLocation(e: DragEvent) {
+ (e.target as HTMLTableDataCellElement).classList.remove('drop-location');
+ }
+
+ // Gets column index in availableColumns based on its attributes.
+ getColumnIndex(columnAttrs: PivotAttrs|AggregationAttrs) {
+ let index = 0;
+ for (const {tableName, columns} of this.availableColumns) {
+ if (tableName === columnAttrs.tableName) {
+ const colIdx =
+ columns.findIndex(column => column === columnAttrs.columnName);
+ return colIdx === -1 ? -1 : index + colIdx;
+ }
+ index += columns.length;
+ }
+ return -1;
+ }
+
+ selectPivotTableColumn(columnAttrs: PivotAttrs|AggregationAttrs) {
+ this._isPivot = !isAggregationAttrs(columnAttrs);
+
+ const colIndex = this.getColumnIndex(columnAttrs);
+ if (colIndex === -1) {
+ throw Error(`Selected column "${columnAttrs.tableName} ${
+ columnAttrs.columnName}" not found in availableColumns.`);
+ }
+ this.setSelectedPivotTableColumnIndex(colIndex);
+
+ if (isAggregationAttrs(columnAttrs)) {
+ const aggIndex = this.availableAggregations.findIndex(
+ aggregation => aggregation === columnAttrs.aggregation);
+ if (aggIndex === -1) {
+ throw Error(`Selected aggregation "${
+ columnAttrs.aggregation}" not found in availableAggregations.`);
+ }
+ this.setSelectedPivotTableAggregationIndex(aggIndex);
+ }
+ }
+
+ queryPivotTableChanges() {
+ globals.dispatch(Actions.setSelectedPivotsAndAggregations({
+ pivotTableId: this.pivotTableId,
+ selectedPivots: this._selectedPivots,
+ selectedAggregations: this._selectedAggregations
+ }));
+ globals.dispatch(Actions.setPivotTableRequest(
+ {pivotTableId: this.pivotTableId, action: 'QUERY'}));
+ }
+
+ toggleEditPivotTableModal() {
+ this._editPivotTableModalOpen = !this._editPivotTableModalOpen;
+ }
+
+ get selectedPivots() {
+ return this._selectedPivots.map(pivot => Object.assign({}, pivot));
+ }
+
+ get selectedAggregations() {
+ return this._selectedAggregations.map(
+ aggregation => Object.assign({}, aggregation));
+ }
+
+ get isPivot() {
+ return this._isPivot;
+ }
+
+ get selectedColumnIndex() {
+ return this._selectedColumnIndex;
+ }
+
+ get selectedAggregationIndex() {
+ return this._selectedAggregationIndex;
+ }
+
+ get editPivotTableModalOpen() {
+ return this._editPivotTableModalOpen;
+ }
+}
diff --git a/ui/src/frontend/pivot_table_helper_unittest.ts b/ui/src/frontend/pivot_table_helper_unittest.ts
new file mode 100644
index 0000000..2f45b1f
--- /dev/null
+++ b/ui/src/frontend/pivot_table_helper_unittest.ts
@@ -0,0 +1,139 @@
+// 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 {SLICE_STACK_COLUMN, TableAttrs} from '../common/pivot_table_common';
+import {PivotTableHelper} from './pivot_table_helper';
+
+const AVAILABLE_COLUMNS: TableAttrs[] =
+ [{tableName: 'slice', columns: ['id', 'type', 'dur', SLICE_STACK_COLUMN]}];
+const ID_COL_IDX = 0;
+const TYPE_COL_IDX = 1;
+const DUR_COL_IDX = 2;
+const STACK_COL_IDX = 3;
+
+const AVAILABLE_AGGREGATIONS = ['SUM', 'AVG'];
+const SUM_AGG_IDX = 0;
+const AVG_AGG_IDX = 1;
+
+function createNewHelper() {
+ return new PivotTableHelper(
+ 'pivotTable', AVAILABLE_COLUMNS, AVAILABLE_AGGREGATIONS, [], []);
+}
+
+test('Update selected pivots based on selected indices', () => {
+ const helper = createNewHelper();
+ helper.setSelectedPivotTableColumnIndex(ID_COL_IDX);
+
+ helper.updatePivotTableColumnOnSelectedIndex();
+ expect(helper.selectedPivots).toEqual([
+ {tableName: 'slice', columnName: 'id', isStackPivot: false}
+ ]);
+
+ helper.updatePivotTableColumnOnSelectedIndex();
+ expect(helper.selectedPivots).toEqual([]);
+});
+
+test('Update selected aggregations based on selected indices', () => {
+ const helper = createNewHelper();
+ helper.togglePivotSelection();
+ helper.setSelectedPivotTableColumnIndex(DUR_COL_IDX);
+ helper.setSelectedPivotTableAggregationIndex(SUM_AGG_IDX);
+
+ helper.updatePivotTableColumnOnSelectedIndex();
+ expect(helper.selectedAggregations).toEqual([
+ {tableName: 'slice', columnName: 'dur', aggregation: 'SUM', order: 'DESC'}
+ ]);
+
+ helper.updatePivotTableColumnOnSelectedIndex();
+ expect(helper.selectedAggregations).toEqual([]);
+});
+
+test('Change aggregation sorting based on aggregation index', () => {
+ const helper = createNewHelper();
+ helper.togglePivotSelection();
+ helper.setSelectedPivotTableColumnIndex(DUR_COL_IDX);
+ helper.setSelectedPivotTableAggregationIndex(SUM_AGG_IDX);
+ helper.updatePivotTableColumnOnSelectedIndex();
+
+ expect(helper.selectedAggregations).toEqual([
+ {tableName: 'slice', columnName: 'dur', aggregation: 'SUM', order: 'DESC'}
+ ]);
+ helper.togglePivotTableAggregationSorting(0);
+ expect(helper.selectedAggregations).toEqual([
+ {tableName: 'slice', columnName: 'dur', aggregation: 'SUM', order: 'ASC'}
+ ]);
+});
+
+test(
+ 'Changing aggregation sorting with invalid index results in an error',
+ () => {
+ const helper = createNewHelper();
+ expect(() => helper.togglePivotTableAggregationSorting(1))
+ .toThrow('Column index "1" is out of bounds.');
+ });
+
+test('Reorder columns based on target and destination indices', () => {
+ const helper = createNewHelper();
+ helper.setSelectedPivotTableColumnIndex(ID_COL_IDX);
+ helper.updatePivotTableColumnOnSelectedIndex();
+ helper.setSelectedPivotTableColumnIndex(TYPE_COL_IDX);
+ helper.updatePivotTableColumnOnSelectedIndex();
+
+ expect(helper.selectedPivots).toEqual([
+ {tableName: 'slice', columnName: 'id', isStackPivot: false},
+ {tableName: 'slice', columnName: 'type', isStackPivot: false}
+ ]);
+ helper.reorderPivotTableDraggedColumn(true, 0, 1);
+ expect(helper.selectedPivots).toEqual([
+ {tableName: 'slice', columnName: 'type', isStackPivot: false},
+ {tableName: 'slice', columnName: 'id', isStackPivot: false}
+ ]);
+});
+
+test('Reordering columns with invalid indices results in an error', () => {
+ const helper = createNewHelper();
+ expect(() => helper.reorderPivotTableDraggedColumn(true, 0, 1))
+ .toThrow('Target column index "0" out of bounds.');
+});
+
+test('Select column based on attributes', () => {
+ const helper = createNewHelper();
+ helper.selectPivotTableColumn({
+ tableName: 'slice',
+ columnName: 'dur',
+ aggregation: 'AVG',
+ order: 'DESC'
+ });
+ expect(helper.isPivot).toEqual(false);
+ expect(helper.selectedColumnIndex).toEqual(DUR_COL_IDX);
+ expect(helper.selectedAggregationIndex).toEqual(AVG_AGG_IDX);
+});
+
+test('Selecting a column with invalid attributes results in an error', () => {
+ const helper = createNewHelper();
+ expect(
+ () => helper.selectPivotTableColumn(
+ {tableName: 'foo', columnName: 'bar', isStackPivot: false}))
+ .toThrow('Selected column "foo bar" not found in availableColumns.');
+});
+
+test('Selecting stack column sets isStackPivot', () => {
+ const helper = createNewHelper();
+ helper.setSelectedPivotTableColumnIndex(STACK_COL_IDX);
+
+ helper.updatePivotTableColumnOnSelectedIndex();
+ expect(helper.selectedPivots).toEqual([
+ {tableName: 'slice', columnName: SLICE_STACK_COLUMN, isStackPivot: true}
+ ]);
+});
diff --git a/ui/src/frontend/post_message_handler.ts b/ui/src/frontend/post_message_handler.ts
index f4ff214..1dcdb54 100644
--- a/ui/src/frontend/post_message_handler.ts
+++ b/ui/src/frontend/post_message_handler.ts
@@ -94,7 +94,7 @@
const openTrace = () => {
// For external traces, we need to disable other features such as
// downloading and sharing a trace.
- globals.frontendLocalState.localOnlyMode = true;
+ postedTrace.localOnly = true;
globals.dispatch(Actions.openTraceFromBuffer(postedTrace));
};
diff --git a/ui/src/frontend/publish.ts b/ui/src/frontend/publish.ts
new file mode 100644
index 0000000..eb2d5fe
--- /dev/null
+++ b/ui/src/frontend/publish.ts
@@ -0,0 +1,194 @@
+// 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 {Actions} from '../common/actions';
+import {AggregateData} from '../common/aggregation_data';
+import {ConversionJobStatusUpdate} from '../common/conversion_jobs';
+import {
+ LogBoundsKey,
+ LogEntriesKey,
+ LogExists,
+ LogExistsKey
+} from '../common/logs';
+import {MetricResult} from '../common/metric_data';
+import {CurrentSearchResults, SearchSummary} from '../common/search_data';
+
+import {
+ CounterDetails,
+ CpuProfileDetails,
+ FlamegraphDetails,
+ Flow,
+ globals,
+ QuantizedLoad,
+ SliceDetails,
+ ThreadDesc,
+ ThreadStateDetails
+} from './globals';
+import {PivotTableHelper} from './pivot_table_helper';
+
+export function publishOverviewData(
+ data: {[key: string]: QuantizedLoad|QuantizedLoad[]}) {
+ for (const [key, value] of Object.entries(data)) {
+ if (!globals.overviewStore.has(key)) {
+ globals.overviewStore.set(key, []);
+ }
+ if (value instanceof Array) {
+ globals.overviewStore.get(key)!.push(...value);
+ } else {
+ globals.overviewStore.get(key)!.push(value);
+ }
+ }
+ globals.rafScheduler.scheduleRedraw();
+}
+
+export function publishTrackData(args: {id: string, data: {}}) {
+ globals.setTrackData(args.id, args.data);
+ if ([LogExistsKey, LogBoundsKey, LogEntriesKey].includes(args.id)) {
+ const data = globals.trackDataStore.get(LogExistsKey) as LogExists;
+ if (data && data.exists) globals.rafScheduler.scheduleFullRedraw();
+ } else {
+ globals.rafScheduler.scheduleRedraw();
+ }
+}
+
+export function publishMetricResult(metricResult: MetricResult) {
+ globals.setMetricResult(metricResult);
+ globals.publishRedraw();
+}
+
+export function publishSelectedFlows(selectedFlows: Flow[]) {
+ globals.selectedFlows = selectedFlows;
+ globals.publishRedraw();
+}
+
+export function publishCounterDetails(click: CounterDetails) {
+ globals.counterDetails = click;
+ globals.publishRedraw();
+}
+
+export function publishFlamegraphDetails(click: FlamegraphDetails) {
+ globals.flamegraphDetails = click;
+ globals.publishRedraw();
+}
+
+export function publishCpuProfileDetails(details: CpuProfileDetails) {
+ globals.cpuProfileDetails = details;
+ globals.publishRedraw();
+}
+
+export function publishHasFtrace(hasFtrace: boolean) {
+ globals.hasFtrace = hasFtrace;
+ globals.publishRedraw();
+}
+
+export function publishConversionJobStatusUpdate(
+ job: ConversionJobStatusUpdate) {
+ globals.setConversionJobStatus(job.jobName, job.jobStatus);
+ globals.publishRedraw();
+}
+
+export function publishLoading(numQueuedQueries: number) {
+ globals.numQueuedQueries = numQueuedQueries;
+ // TODO(hjd): Clean up loadingAnimation given that this now causes a full
+ // redraw anyways. Also this should probably just go via the global state.
+ globals.rafScheduler.scheduleFullRedraw();
+}
+
+export function publishBufferUsage(args: {percentage: number}) {
+ globals.setBufferUsage(args.percentage);
+ globals.publishRedraw();
+}
+
+export function publishSearch(args: SearchSummary) {
+ globals.searchSummary = args;
+ globals.publishRedraw();
+}
+
+export function publishSearchResult(args: CurrentSearchResults) {
+ globals.currentSearchResults = args;
+ globals.publishRedraw();
+}
+
+export function publishRecordingLog(args: {logs: string}) {
+ globals.setRecordingLog(args.logs);
+ globals.publishRedraw();
+}
+
+export function publishTraceErrors(numErrors: number) {
+ globals.setTraceErrors(numErrors);
+ globals.publishRedraw();
+}
+
+export function publishMetricError(error: string) {
+ globals.setMetricError(error);
+ globals.logging.logError(error, false);
+ globals.publishRedraw();
+}
+
+export function publishAggregateData(
+ args: {data: AggregateData, kind: string}) {
+ globals.setAggregateData(args.kind, args.data);
+ globals.publishRedraw();
+}
+
+export function publishQueryResult(args: {id: string, data?: {}}) {
+ globals.queryResults.set(args.id, args.data);
+ globals.publishRedraw();
+}
+
+export function publishPivotTableHelper(
+ args: {id: string, data: PivotTableHelper}) {
+ globals.pivotTableHelper.set(args.id, args.data);
+ globals.publishRedraw();
+}
+
+export function publishThreads(data: ThreadDesc[]) {
+ globals.threads.clear();
+ data.forEach(thread => {
+ globals.threads.set(thread.utid, thread);
+ });
+ globals.publishRedraw();
+}
+
+export function publishSliceDetails(click: SliceDetails) {
+ globals.sliceDetails = click;
+ globals.publishRedraw();
+}
+
+export function publishThreadStateDetails(click: ThreadStateDetails) {
+ globals.threadStateDetails = click;
+ globals.publishRedraw();
+}
+
+export function publishConnectedFlows(connectedFlows: Flow[]) {
+ globals.connectedFlows = connectedFlows;
+ // 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.
+ globals.dispatch(Actions.setHighlightedFlowLeftId({flowId: -1}));
+ globals.dispatch(Actions.setHighlightedFlowRightId({flowId: -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.dispatch(Actions.setHighlightedFlowRightId({flowId: flow.id}));
+ }
+ if (flow.end.sliceId === sliceId) {
+ globals.dispatch(Actions.setHighlightedFlowLeftId({flowId: flow.id}));
+ }
+ }
+ }
+
+ globals.publishRedraw();
+}
diff --git a/ui/src/frontend/query_table.ts b/ui/src/frontend/query_table.ts
index f69a8ba..6b48524 100644
--- a/ui/src/frontend/query_table.ts
+++ b/ui/src/frontend/query_table.ts
@@ -16,13 +16,14 @@
import * as m from 'mithril';
import {Actions} from '../common/actions';
-import {Row} from '../common/protos';
import {QueryResponse} from '../common/queries';
+import {Row} from '../common/query_result';
import {fromNs} from '../common/time';
-import {copyToClipboard} from './clipboard';
+import {queryResponseToClipboard} from './clipboard';
import {globals} from './globals';
import {Panel} from './panel';
+import {Router} from './router';
import {
findUiTrackId,
horizontalScrollAndZoomToRange,
@@ -46,7 +47,7 @@
static rowOnClickHandler(
event: Event, row: Row, nextTab: 'CurrentSelection'|'QueryResults') {
// TODO(dproy): Make click handler work from analyze page.
- if (globals.state.route !== '/viewer') return;
+ if (Router.parseUrl(window.location.href).page !== '/viewer') return;
// If the click bubbles up to the pan and zoom handler that will deselect
// the slice.
event.stopPropagation();
@@ -70,7 +71,7 @@
globals.makeSelection(
Actions.selectChromeSlice(
{id: sliceId, trackId: uiTrackId, table: 'slice'}),
- nextTab === 'QueryResults' ? globals.frontendLocalState.currentTab :
+ nextTab === 'QueryResults' ? globals.state.currentTab :
'current_selection');
}
}
@@ -141,25 +142,14 @@
'header.overview',
`Query result - ${Math.round(resp.durationMs)} ms`,
m('span.code', resp.query),
- resp.error ?
- null :
- m('button.query-ctrl',
- {
- onclick: () => {
- const lines: string[][] = [];
- lines.push(resp.columns);
- for (const row of resp.rows) {
- const line = [];
- for (const col of resp.columns) {
- line.push(row[col].toString());
- }
- lines.push(line);
- }
- copyToClipboard(
- lines.map(line => line.join('\t')).join('\n'));
- },
- },
- 'Copy as .tsv'),
+ resp.error ? null :
+ m('button.query-ctrl',
+ {
+ onclick: () => {
+ queryResponseToClipboard(resp);
+ },
+ },
+ 'Copy as .tsv'),
m('button.query-ctrl',
{
onclick: () => {
diff --git a/ui/src/frontend/raf_scheduler.ts b/ui/src/frontend/raf_scheduler.ts
index dd708c2..eccf094 100644
--- a/ui/src/frontend/raf_scheduler.ts
+++ b/ui/src/frontend/raf_scheduler.ts
@@ -115,6 +115,10 @@
}
}
+ get hasPendingRedraws(): boolean {
+ return this.isRedrawing || this.hasScheduledNextFrame;
+ }
+
private syncCanvasRedraw(nowMs: number) {
const redrawStart = debugNow();
if (this.isRedrawing) return;
diff --git a/ui/src/frontend/record_config.ts b/ui/src/frontend/record_config.ts
index 029f6f0..2676b31 100644
--- a/ui/src/frontend/record_config.ts
+++ b/ui/src/frontend/record_config.ts
@@ -13,7 +13,7 @@
// limitations under the License.
import {RecordConfig} from '../common/state';
-import {validateRecordConfig} from '../controller/validate_config';
+import {JsonObject, validateRecordConfig} from '../controller/validate_config';
const LOCAL_STORAGE_RECORD_CONFIGS_KEY = 'recordConfigs';
@@ -24,19 +24,10 @@
constructor(title: string, config: RecordConfig, key: string) {
this.title = title;
- this.config = this.validateData(config);
+ this.config = validateRecordConfig(config as unknown as JsonObject);
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 &&
diff --git a/ui/src/frontend/record_page.ts b/ui/src/frontend/record_page.ts
index 575b2c8..ec62542 100644
--- a/ui/src/frontend/record_page.ts
+++ b/ui/src/frontend/record_page.ts
@@ -17,6 +17,7 @@
import * as m from 'mithril';
import {Actions} from '../common/actions';
+import {featureFlags} from '../common/feature_flags';
import {MeminfoCounters, VmstatCounters} from '../common/protos';
import {
AdbRecordingTarget,
@@ -28,13 +29,14 @@
isAndroidTarget,
isChromeTarget,
isCrOSTarget,
- RecordingTarget
+ MAX_TIME,
+ RecordingTarget,
+ RecordMode
} from '../common/state';
-import {MAX_TIME, RecordMode} from '../common/state';
import {AdbOverWebUsb} from '../controller/adb';
import {globals} from './globals';
-import {createPage} from './pages';
+import {createPage, PageAttrs} from './pages';
import {recordConfigStore} from './record_config';
import {
CodeSnippet,
@@ -42,6 +44,7 @@
DropdownAttrs,
Probe,
ProbeAttrs,
+ SelectAllNoneDropdown,
Slider,
SliderAttrs,
Textarea,
@@ -49,9 +52,13 @@
Toggle,
ToggleAttrs
} from './record_widgets';
-import {Router} from './router';
-const LOCAL_STORAGE_SHOW_CONFIG = 'showConfigs';
+const PERSIST_CONFIG_FLAG = featureFlags.register({
+ id: 'persistConfigsUI',
+ name: 'Config persistence UI',
+ description: 'Show experimental config persistence UI on the record page.',
+ defaultValue: false,
+});
const POLL_INTERVAL_MS = [250, 500, 1000, 2500, 5000, 30000, 60000];
@@ -716,40 +723,34 @@
categories = getBuiltinChromeCategoryList();
}
- // Show "disabled-by-default" categories last.
- const categoriesMap = new Map<string, string>();
+ const defaultCategories = new Map<string, string>();
+ const disabledByDefaultCategories = new Map<string, string>();
const disabledPrefix = 'disabled-by-default-';
- const overheadSuffix = '(high overhead)';
categories.forEach(cat => {
if (cat.startsWith(disabledPrefix)) {
- categoriesMap.set(
- cat, `${cat.replace(disabledPrefix, '')} ${overheadSuffix}`);
+ disabledByDefaultCategories.set(cat, cat.replace(disabledPrefix, ''));
} else {
- categoriesMap.set(cat, cat);
+ defaultCategories.set(cat, cat);
}
});
- return m(Dropdown, {
- title: 'Additional Chrome categories',
- cssClass: '.multicolumn.two-columns',
- options: categoriesMap,
- set: (cfg, val) => cfg.chromeCategoriesSelected = val,
- get: (cfg) => cfg.chromeCategoriesSelected,
- sort: (a, b) => {
- const aIsDisabled = a.includes(overheadSuffix);
- const bIsDisabled = b.includes(overheadSuffix);
- if (aIsDisabled === bIsDisabled) {
- return a.localeCompare(b);
- } else {
- return Number(aIsDisabled) - Number(bIsDisabled);
- }
- },
- } as DropdownAttrs);
+ return m(
+ '.chrome-categories',
+ SelectAllNoneDropdown({
+ categories: defaultCategories,
+ title: 'Additional Chrome categories',
+ get: (cfg) => cfg.chromeCategoriesSelected,
+ set: (cfg, val) => cfg.chromeCategoriesSelected = val,
+ }),
+ SelectAllNoneDropdown({
+ categories: disabledByDefaultCategories,
+ title: 'Additional high overhead Chrome categories',
+ get: (cfg) => cfg.chromeHighOverheadCategoriesSelected,
+ set: (cfg, val) => cfg.chromeHighOverheadCategoriesSelected = val,
+ }));
}
function AdvancedSettings(cssClass: string) {
- const S = (x: number) => x * 1000;
- const M = (x: number) => x * 1000 * 60;
return m(
`.record-section${cssClass}`,
m(Probe,
@@ -762,6 +763,14 @@
setEnabled: (cfg, val) => cfg.ftrace = val,
isEnabled: (cfg) => cfg.ftrace
} as ProbeAttrs,
+ m(Toggle, {
+ title: 'Resolve kernel symbols',
+ cssClass: '.thin',
+ descr: `Enables lookup via /proc/kallsyms for workqueue,
+ sched_blocked_reason and other events (userdebug/eng builds only).`,
+ setEnabled: (cfg, val) => cfg.symbolizeKsyms = val,
+ isEnabled: (cfg) => cfg.symbolizeKsyms
+ } as ToggleAttrs),
m(Slider, {
title: 'Buf size',
cssClass: '.thin',
@@ -791,27 +800,7 @@
'kmem/*',
set: (cfg, val) => cfg.ftraceExtraEvents = val,
get: (cfg) => cfg.ftraceExtraEvents
- } as TextareaAttrs)),
- globals.state.videoEnabled ?
- m(Probe,
- {
- title: 'Screen recording',
- img: null,
- descr: `Records the screen along with running a trace. Max
- time of recording is 3 minutes (180 seconds).`,
- setEnabled: (cfg, val) => cfg.screenRecord = val,
- isEnabled: (cfg) => cfg.screenRecord,
- } as ProbeAttrs,
- m(Slider, {
- title: 'Max duration',
- icon: 'timer',
- values: [S(10), S(15), S(30), S(60), M(2), M(3)],
- isTime: true,
- unit: 'm:s',
- set: (cfg, val) => cfg.durationMs = val,
- get: (cfg) => cfg.durationMs,
- } as SliderAttrs)) :
- null);
+ } as TextareaAttrs)));
}
function RecordHeader() {
@@ -894,7 +883,7 @@
return m(
`.record-section.instructions${cssClass}`,
m('header', 'Recording command'),
- localStorage.hasOwnProperty(LOCAL_STORAGE_SHOW_CONFIG) ?
+ PERSIST_CONFIG_FLAG.get() ?
m('button.permalinkconfig',
{
onclick: () => {
@@ -1121,12 +1110,6 @@
const pbBase64 = data ? data.pbBase64 : '';
const pbtx = data ? data.pbtxt : '';
let cmd = '';
- if (cfg.screenRecord) {
- // Half-second delay to ensure Perfetto starts tracing before screenrecord
- // starts recording
- cmd += `(sleep 0.5 && adb shell screenrecord --time-limit ${time}`;
- cmd += ' "/sdcard/tracescr.mp4") &\\\n';
- }
if (isAndroidP(target)) {
cmd += `echo '${pbBase64}' | \n`;
cmd += 'base64 --decode | \n';
@@ -1186,7 +1169,7 @@
}
function onStartRecordingPressed() {
- location.href = '#!/record?p=instructions';
+ location.href = '#!/record/instructions';
globals.rafScheduler.scheduleFullRedraw();
const target = globals.state.recordingTarget;
@@ -1303,7 +1286,7 @@
function recordMenu(routePage: string) {
const target = globals.state.recordingTarget;
const chromeProbe =
- m('a[href="#!/record?p=chrome"]',
+ m('a[href="#!/record/chrome"]',
m(`li${routePage === 'chrome' ? '.active' : ''}`,
m('i.material-icons', 'laptop_chromebook'),
m('.title', 'Chrome'),
@@ -1318,18 +1301,18 @@
},
m('header', 'Trace config'),
m('ul',
- m('a[href="#!/record?p=buffers"]',
+ m('a[href="#!/record/buffers"]',
m(`li${routePage === 'buffers' ? '.active' : ''}`,
m('i.material-icons', 'tune'),
m('.title', 'Recording settings'),
m('.sub', 'Buffer mode, size and duration'))),
- m('a[href="#!/record?p=instructions"]',
+ m('a[href="#!/record/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"]',
+ PERSIST_CONFIG_FLAG.get() ?
+ m('a[href="#!/record/config"]',
{
onclick: () => {
recordConfigStore.reloadFromLocalStorage();
@@ -1343,33 +1326,33 @@
m('header', 'Probes'),
m('ul',
isChromeTarget(target) && !isCrOSTarget(target) ? [chromeProbe] : [
- m('a[href="#!/record?p=cpu"]',
+ m('a[href="#!/record/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('a[href="#!/record/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('a[href="#!/record/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('a[href="#!/record/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('a[href="#!/record/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('a[href="#!/record/advanced"]',
m(`li${routePage === 'advanced' ? '.active' : ''}`,
m('i.material-icons', 'settings'),
m('.title', 'Advanced settings'),
@@ -1379,7 +1362,7 @@
export const RecordPage = createPage({
- view() {
+ view({attrs}: m.Vnode<PageAttrs>) {
const SECTIONS: {[property: string]: (cssClass: string) => m.Child} = {
buffers: RecSettings,
instructions: Instructions,
@@ -1394,8 +1377,8 @@
};
const pages: m.Children = [];
- const routePageParam = Router.param('p');
- let routePage = typeof routePageParam === 'string' ? routePageParam : '';
+ // we need to remove the `/` character from the route
+ let routePage = attrs.subpage ? attrs.subpage.substr(1) : '';
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 4f71447..af3e384 100644
--- a/ui/src/frontend/record_widgets.ts
+++ b/ui/src/frontend/record_widgets.ts
@@ -340,3 +340,46 @@
);
}
}
+
+// Dropdown augmented with select all/none buttons
+export function SelectAllNoneDropdown(args: {
+ categories: Map<string, string>,
+ title: string,
+ get: Getter<string[]>,
+ set: Setter<string[]>,
+}) {
+ return m(
+ '.categories-list',
+ m('button.config-button',
+ {
+ onclick: () => {
+ const config = produce(globals.state.recordConfig, draft => {
+ args.set(draft, Array.from(args.categories.keys()));
+ });
+ globals.dispatch(Actions.setRecordConfig({config}));
+ }
+ },
+ 'All'),
+ m('button.config-button',
+ {
+ onclick: () => {
+ const config = produce(globals.state.recordConfig, draft => {
+ args.set(draft, Array.from([]));
+ });
+ globals.dispatch(Actions.setRecordConfig({config}));
+ },
+ },
+ 'None'),
+ m('br'),
+ m(Dropdown, {
+ cssClass: '.singlecolumn',
+ title: args.title,
+ options: args.categories,
+ set: args.set,
+ get: args.get,
+ sort: (a, b) => {
+ return a.localeCompare(b);
+ },
+ } as DropdownAttrs),
+ );
+}
diff --git a/ui/src/frontend/router.ts b/ui/src/frontend/router.ts
index 1c6a539..c288b58 100644
--- a/ui/src/frontend/router.ts
+++ b/ui/src/frontend/router.ts
@@ -13,83 +13,195 @@
// limitations under the License.
import * as m from 'mithril';
-
-import {Actions, DeferredAction} from '../common/actions';
-import {Analytics} from '../frontend/analytics';
-
-interface RouteMap {
- [route: string]: m.Component;
-}
+import {assertExists, assertTrue} from '../base/logging';
+import {PageAttrs} from './pages';
export const ROUTE_PREFIX = '#!';
+const DEFAULT_ROUTE = '/';
+/*
+ * A broken down representation of a route.
+ * For instance: #!/record/gpu?trace_id=a0b1c2
+ * becomes: {page: '/record', subpage: '/gpu', args: {trace_id: 'a0b1c2'}}
+ */
+export interface Route {
+ page: string;
+ subpage: string;
+ args: RouteArgs;
+}
+
+/*
+ * The set of args that can be set on the route via #!/page?a=1&b2.
+ * Route args are orthogonal to pages (i.e. should NOT make sense only in a
+ * only within a specific page, use /page/subpages for that).
+ * Args are !== the querystring (location.search) which is sent to the
+ * server. The route args are NOT sent to the HTTP server.
+ * Given this URL:
+ * http://host/?foo=1&bar=2#!/page/subpage?trace_id=a0b1c2&baz=3.
+ *
+ * location.search = 'foo=1&bar=2'.
+ * This is seen by the HTTP server. We really don't use querystrings as the
+ * perfetto UI is client only.
+ *
+ * location.hash = '#!/page/subpage?trace_id=a0b1c2'.
+ * This is client-only. All the routing logic in the Perfetto UI uses only
+ * this.
+ */
+export interface RouteArgs {
+ // The trace_id is special and is persisted across navigations.
+ trace_id?: string;
+
+ // These are transient and are really set only on startup.
+ openFromAndroidBugTool?: string;
+ s?: string; // For permalinks.
+ p?: string; // DEPRECATED: for #!/record?p=cpu subpages (b/191255021).
+ url?: string; // For fetching traces from Cloud Storage.
+}
+
+export interface RoutesMap {
+ [key: string]: m.Component<PageAttrs>;
+}
+
+/*
+ * This router does two things:
+ * 1) Maps fragment paths (#!/page/subpage) to Mithril components.
+ * The route map is passed to the ctor and is later used when calling the
+ * resolve() method.
+ *
+ * 2) Handles the (optional) args, e.g. #!/page?arg=1&arg2=2.
+ * Route args are carry information that is orthogonal to the page (e.g. the
+ * trace id).
+ * trace_id has some special treatment: once a URL has a trace_id argument,
+ * it gets automatically appended to further navigations that don't have one.
+ * For instance if the current url is #!/viewer?trace_id=1234 and a later
+ * action (either user-initiated or code-initited) navigates to #!/info, the
+ * rotuer will automatically replace the history entry with
+ * #!/info?trace_id=1234.
+ * This is to keep propagating the trace id across page changes, for handling
+ * tab discards (b/175041881).
+ *
+ * This class does NOT deal with the "load a trace when the url contains ?url=
+ * or ?trace_id=". That logic lives in trace_url_handler.ts, which is triggered
+ * by Router.onRouteChanged().
+ */
export class Router {
- constructor(
- private defaultRoute: string, private routes: RouteMap,
- private dispatch: (a: DeferredAction) => void,
- private logging: Analytics) {
- if (!(defaultRoute in routes)) {
- throw Error('routes must define a component for defaultRoute.');
+ private readonly recentChanges: number[] = [];
+ private routes: RoutesMap;
+
+ // frontend/index.ts calls maybeOpenTraceFromRoute() + redraw here.
+ // This event is decoupled for testing and to avoid circular deps.
+ onRouteChanged: (route: Route) => (void) = () => {};
+
+ constructor(routes: RoutesMap) {
+ assertExists(routes[DEFAULT_ROUTE]);
+ this.routes = routes;
+ window.onhashchange = (e: HashChangeEvent) => this.onHashChange(e);
+ }
+
+ private onHashChange(e: HashChangeEvent) {
+ this.crashIfLivelock();
+
+ const oldRoute = Router.parseUrl(e.oldURL);
+ const newRoute = Router.parseUrl(e.newURL);
+
+ if (newRoute.args.trace_id === undefined && oldRoute.args.trace_id) {
+ // Propagate the trace_id across navigations. When a trace is loaded, the
+ // URL becomes #!/viewer?trace_id=a0b1c2. The ?trace_id arg allows
+ // reopening the trace from cache in the case of a reload or discard.
+ // When using the UI we can hit "bare" links (e.g. just '#!/info') which
+ // don't have the trace_uuid:
+ // - When clicking on an <a> element from the sidebar.
+ // - When the code calls Router.navigate().
+ // - When the user pastes a URL from docs page.
+ // In all these cases we want to keep propagating the trace_id argument.
+ // We do so by re-setting the trace_id argument and doing a
+ // location.replace which overwrites the history entry (note
+ // location.replace is NOT just a String.replace operation).
+ newRoute.args.trace_id = oldRoute.args.trace_id;
}
- window.onhashchange = () => this.navigateToCurrentHash();
+ const args = m.buildQueryString(newRoute.args);
+ let normalizedFragment = `#!${newRoute.page}${newRoute.subpage}`;
+ normalizedFragment += args.length > 0 ? '?' + args : '';
+ if (!e.newURL.endsWith(normalizedFragment)) {
+ location.replace(normalizedFragment);
+ return;
+ }
+
+ this.onRouteChanged(newRoute);
}
/**
- * Parses and returns the current route string from |window.location.hash|.
- * May return routes that are not defined in |this.routes|.
+ * Returns the component for the current route in the URL.
+ * If no route matches the URL, returns a component corresponding to
+ * |this.defaultRoute|.
*/
- getRouteFromHash(): string {
+ resolve(): m.Vnode<PageAttrs> {
+ const route = Router.parseFragment(location.hash);
+ let component = this.routes[route.page];
+ if (component === undefined) {
+ component = assertExists(this.routes[DEFAULT_ROUTE]);
+ }
+ return m(component, {subpage: route.subpage} as PageAttrs);
+ }
+
+ static navigate(newHash: string) {
+ assertTrue(newHash.startsWith(ROUTE_PREFIX));
+ window.location.hash = newHash;
+ }
+
+ /*
+ * Breaks down a fragment into a Route object.
+ * Sample input:
+ * '#!/record/gpu?trace_id=629329-18bba4'
+ * Sample output:
+ * {page: '/record', subpage: '/gpu', args: {trace_id: '629329-18bba4'}}
+ */
+ static parseFragment(hash: string): Route {
const prefixLength = ROUTE_PREFIX.length;
- const hash = window.location.hash;
-
- // Do not try to parse route if prefix doesn't match.
- if (hash.substring(0, prefixLength) !== ROUTE_PREFIX) return '';
-
- return hash.split('?')[0].substring(prefixLength);
- }
-
- /**
- * Sets |route| on |window.location.hash|. If |route| if not defined in
- * |this.routes|, dispatches a navigation to |this.defaultRoute|.
- */
- setRouteOnHash(route: string) {
- history.pushState(undefined, "", ROUTE_PREFIX + route);
- this.logging.updatePath(route);
-
- if (!(route in this.routes)) {
- console.info(
- `Route ${route} not known redirecting to ${this.defaultRoute}.`);
- this.dispatch(Actions.navigate({route: this.defaultRoute}));
+ let route = '';
+ if (hash.startsWith(ROUTE_PREFIX)) {
+ route = hash.substr(prefixLength).split('?')[0];
}
- }
- /**
- * Dispatches navigation action to |this.getRouteFromHash()| if that is
- * defined in |this.routes|, otherwise to |this.defaultRoute|.
- */
- navigateToCurrentHash() {
- const hashRoute = this.getRouteFromHash();
- const newRoute = hashRoute in this.routes ? hashRoute : this.defaultRoute;
- this.dispatch(Actions.navigate({route: newRoute}));
- // TODO(dproy): Handle case when new route has a permalink.
- }
-
- /**
- * Returns the component for given |route|. If |route| is not defined, returns
- * component of |this.defaultRoute|.
- */
- resolve(route: string|null): m.Component {
- if (!route || !(route in this.routes)) {
- return this.routes[this.defaultRoute];
+ let page = route;
+ let subpage = '';
+ const splittingPoint = route.indexOf('/', 1);
+ if (splittingPoint > 0) {
+ page = route.substr(0, splittingPoint);
+ subpage = route.substr(splittingPoint);
}
- return this.routes[route];
+
+ const argsStart = hash.indexOf('?');
+ const argsStr = argsStart < 0 ? '' : hash.substr(argsStart + 1);
+ const args = argsStr ? m.parseQueryString(hash.substr(argsStart)) : {};
+
+ return {page, subpage, args};
}
- static param(key: string) {
- const hash = window.location.hash;
- const paramStart = hash.indexOf('?');
- if (paramStart === -1) return undefined;
- return m.parseQueryString(hash.substring(paramStart))[key];
+ /*
+ * Like parseFragment() but takes a full URL.
+ */
+ static parseUrl(url: string): Route {
+ const hashPos = url.indexOf('#');
+ const fragment = hashPos < 0 ? '' : url.substr(hashPos);
+ return Router.parseFragment(fragment);
+ }
+
+ /*
+ * Throws if EVENT_LIMIT onhashchange events occur within WINDOW_MS.
+ */
+ private crashIfLivelock() {
+ const WINDOW_MS = 1000;
+ const EVENT_LIMIT = 20;
+ const now = Date.now();
+ while (this.recentChanges.length > 0 &&
+ now - this.recentChanges[0] > WINDOW_MS) {
+ this.recentChanges.shift();
+ }
+ this.recentChanges.push(now);
+ if (this.recentChanges.length > EVENT_LIMIT) {
+ throw new Error('History rewriting livelock');
+ }
}
}
diff --git a/ui/src/frontend/router_jsdomtest.ts b/ui/src/frontend/router_jsdomtest.ts
deleted file mode 100644
index 0d77e5b..0000000
--- a/ui/src/frontend/router_jsdomtest.ts
+++ /dev/null
@@ -1,144 +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 {dingus} from 'dingusjs';
-
-import {Actions, DeferredAction} from '../common/actions';
-
-import {NullAnalytics} from './analytics';
-import {Router} from './router';
-
-const mockComponent = {
- view() {}
-};
-
-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();
-});
-
-test('Resolves empty route to default component', () => {
- const router =
- new Router('/a', {'/a': mockComponent}, fakeDispatch, mockLogging);
- expect(router.resolve('')).toBe(mockComponent);
- expect(router.resolve(null)).toBe(mockComponent);
-});
-
-test('Parse route from hash', () => {
- const router =
- new Router('/', {'/': mockComponent}, fakeDispatch, mockLogging);
- window.location.hash = '#!/foobar?s=42';
- expect(router.getRouteFromHash()).toBe('/foobar');
-
- window.location.hash = '/foobar'; // Invalid prefix.
- expect(router.getRouteFromHash()).toBe('');
-});
-
-test('Set valid route on hash', () => {
- const dispatch = dingus<(a: DeferredAction) => void>();
- const router = new Router(
- '/',
- {
- '/': mockComponent,
- '/a': mockComponent,
- },
- dispatch,
- mockLogging);
- const prevHistoryLength = window.history.length;
-
- router.setRouteOnHash('/a');
- expect(window.location.hash).toBe('#!/a');
- expect(window.history.length).toBe(prevHistoryLength + 1);
- // No navigation action should be dispatched.
- expect(dispatch.calls.length).toBe(0);
-});
-
-test('Redirects to default for invalid route in setRouteOnHash ', () => {
- const dispatch = dingus<(a: DeferredAction) => void>();
- // const dispatch = () => {console.log("action received")};
-
- const router = new Router('/', {'/': mockComponent}, dispatch, mockLogging);
- router.setRouteOnHash('foo');
- expect(dispatch.calls.length).toBe(1);
- expect(dispatch.calls[0][1].length).toBeGreaterThanOrEqual(1);
- expect(dispatch.calls[0][1][0]).toEqual(Actions.navigate({route: '/'}));
-});
-
-test('Navigate on hash change', done => {
- const mockDispatch = (a: DeferredAction) => {
- expect(a).toEqual(Actions.navigate({route: '/viewer'}));
- done();
- };
- new Router(
- '/',
- {
- '/': mockComponent,
- '/viewer': mockComponent,
- },
- mockDispatch,
- mockLogging);
- window.location.hash = '#!/viewer';
-});
-
-test('Redirects to default when invalid route set in window location', done => {
- const mockDispatch = (a: DeferredAction) => {
- expect(a).toEqual(Actions.navigate({route: '/'}));
- done();
- };
-
- new Router(
- '/',
- {
- '/': mockComponent,
- '/viewer': mockComponent,
- },
- mockDispatch,
- mockLogging);
-
- window.location.hash = '#invalid';
-});
-
-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);
- router.navigateToCurrentHash();
- expect(dispatch.calls[0][1][0]).toEqual(Actions.navigate({route: '/b'}));
-});
-
-test('navigateToCurrentHash with invalid current route', () => {
- const dispatch = dingus<(a: DeferredAction) => void>();
- window.location.hash = '#!/invalid';
- const router = new Router('/', {'/': mockComponent}, dispatch, mockLogging);
- router.navigateToCurrentHash();
- expect(dispatch.calls[0][1][0]).toEqual(Actions.navigate({route: '/'}));
-});
-
-test('Params parsing', () => {
- window.location.hash = '#!/foo?a=123&b=42&c=a?b?c';
- expect(Router.param('a')).toBe('123');
- expect(Router.param('b')).toBe('42');
- expect(Router.param('c')).toBe('a?b?c');
-});
diff --git a/ui/src/frontend/router_unittest.ts b/ui/src/frontend/router_unittest.ts
new file mode 100644
index 0000000..28bf107
--- /dev/null
+++ b/ui/src/frontend/router_unittest.ts
@@ -0,0 +1,106 @@
+// 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 {Router} from './router';
+
+const mockComponent = {
+ view() {}
+};
+
+beforeEach(() => {
+ window.location.hash = '';
+});
+
+test('Default route must be defined', () => {
+ expect(() => new Router({'/a': mockComponent})).toThrow();
+});
+
+test('Resolves empty route to default component', () => {
+ const router = new Router({'/': mockComponent});
+ window.location.hash = '';
+ expect(router.resolve().tag).toBe(mockComponent);
+});
+
+test('Resolves subpage route to component of main page', () => {
+ const nonDefaultComponent = {view() {}};
+ const router = new Router({
+ '/': mockComponent,
+ '/a': nonDefaultComponent,
+ });
+ window.location.hash = '#!/a/subpage';
+ expect(router.resolve().tag).toBe(nonDefaultComponent);
+ expect(router.resolve().attrs.subpage).toBe('/subpage');
+});
+
+test('Pass empty subpage if not found in URL', () => {
+ const nonDefaultComponent = {view() {}};
+ const router = new Router({
+ '/': mockComponent,
+ '/a': nonDefaultComponent,
+ });
+ window.location.hash = '#!/a';
+ expect(router.resolve().tag).toBe(nonDefaultComponent);
+ expect(router.resolve().attrs.subpage).toBe('');
+});
+
+test('Args parsing', () => {
+ const url = 'http://localhost/#!/foo?p=123&s=42&url=a?b?c';
+ const args = Router.parseUrl(url).args;
+ expect(args.p).toBe('123');
+ expect(args.s).toBe('42');
+ expect(args.url).toBe('a?b?c');
+});
+
+test('empty route broken into empty components', () => {
+ const {page, subpage, args} = Router.parseFragment('');
+ expect(page).toBe('');
+ expect(subpage).toBe('');
+ expect(args).toEqual({});
+});
+
+test('invalid route broken into empty components', () => {
+ const {page, subpage, args} = Router.parseFragment('/bla');
+ expect(page).toBe('');
+ expect(subpage).toBe('');
+ expect(args).toEqual({});
+});
+
+test('simple route has page defined', () => {
+ const {page, subpage, args} = Router.parseFragment('#!/record');
+ expect(page).toBe('/record');
+ expect(subpage).toBe('');
+ expect(args).toEqual({});
+});
+
+test('simple route has both components defined', () => {
+ const {page, subpage, args} = Router.parseFragment('#!/record/memory');
+ expect(page).toBe('/record');
+ expect(subpage).toBe('/memory');
+ expect(args).toEqual({});
+});
+
+test('route broken at first slash', () => {
+ const {page, subpage, args} = Router.parseFragment('#!/record/memory/stuff');
+ expect(page).toBe('/record');
+ expect(subpage).toBe('/memory/stuff');
+ expect(args).toEqual({});
+});
+
+test('parameters separated from route', () => {
+ const {page, subpage, args} =
+ Router.parseFragment('#!/record/memory?url=http://localhost:1234/aaaa');
+ expect(page).toBe('/record');
+ expect(subpage).toBe('/memory');
+ expect(args).toEqual({url: 'http://localhost:1234/aaaa'});
+});
diff --git a/ui/src/frontend/rpc_http_dialog.ts b/ui/src/frontend/rpc_http_dialog.ts
index 77ee0fe..30a25b3 100644
--- a/ui/src/frontend/rpc_http_dialog.ts
+++ b/ui/src/frontend/rpc_http_dialog.ts
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import '../tracks/all_frontend';
-
import * as m from 'mithril';
import {assertExists} from '../base/logging';
diff --git a/ui/src/frontend/search_handler.ts b/ui/src/frontend/search_handler.ts
index cfdc259..1655c69 100644
--- a/ui/src/frontend/search_handler.ts
+++ b/ui/src/frontend/search_handler.ts
@@ -20,17 +20,18 @@
import {scrollToTrackAndTs} from './scroll_helper';
function setToPrevious(current: number) {
- globals.frontendLocalState.setSearchIndex(Math.max(current - 1, 0));
+ const index = Math.max(current - 1, 0);
+ globals.dispatch(Actions.setSearchIndex({index}));
}
function setToNext(current: number) {
- globals.frontendLocalState.setSearchIndex(
- Math.min(current + 1, globals.currentSearchResults.totalResults - 1));
+ const index =
+ Math.min(current + 1, globals.currentSearchResults.totalResults - 1);
+ globals.dispatch(Actions.setSearchIndex({index}));
}
export function executeSearch(reverse = false) {
- const state = globals.frontendLocalState;
- const index = state.searchIndex;
+ const index = globals.state.searchIndex;
const startNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
const currentTs = globals.currentSearchResults.tsStarts[index];
@@ -42,14 +43,20 @@
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);
+ if (smaller === -1) {
+ setToPrevious(index);
+ } else {
+ globals.dispatch(Actions.setSearchIndex({index: 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);
+ if (larger === -1) {
+ setToNext(index);
+ } else {
+ globals.dispatch(Actions.setSearchIndex({index: larger}));
+ }
}
} else {
// If the currentTs is in the viewport, increment the index.
@@ -72,7 +79,7 @@
}
function moveViewportToCurrentSearch() {
- const searchIndex = globals.frontendLocalState.searchIndex;
+ const searchIndex = globals.state.searchIndex;
if (searchIndex === -1) return;
const currentTs = globals.currentSearchResults.tsStarts[searchIndex];
const trackId = globals.currentSearchResults.trackIds[searchIndex];
@@ -80,8 +87,7 @@
}
function selectCurrentSearchResult() {
- const state = globals.frontendLocalState;
- const searchIndex = state.searchIndex;
+ const searchIndex = globals.state.searchIndex;
const source = globals.currentSearchResults.sources[searchIndex];
const currentId = globals.currentSearchResults.sliceIds[searchIndex];
const trackId = globals.currentSearchResults.trackIds[searchIndex];
diff --git a/ui/src/frontend/service_worker_controller.ts b/ui/src/frontend/service_worker_controller.ts
index bc11ee3..66abfc9 100644
--- a/ui/src/frontend/service_worker_controller.ts
+++ b/ui/src/frontend/service_worker_controller.ts
@@ -43,6 +43,9 @@
}
} else {
await caches.delete(BYPASS_ID);
+ if (window.localStorage) {
+ window.localStorage.setItem('bypassDisabled', '1');
+ }
this.install();
}
globals.rafScheduler.scheduleFullRedraw();
@@ -81,6 +84,16 @@
return;
}
+ // If this is localhost disable the service worker by default, unless the
+ // user manually re-enabled it (in which case bypassDisabled = '1').
+ const hostname = location.hostname;
+ const isLocalhost = ['127.0.0.1', '::1', 'localhost'].includes(hostname);
+ const bypassDisabled = window.localStorage &&
+ window.localStorage.getItem('bypassDisabled') === '1';
+ if (isLocalhost && !bypassDisabled) {
+ await this.setBypass(true); // Will cause the check below to bail out.
+ }
+
if (await caches.has(BYPASS_ID)) {
this._bypassed = true;
console.log('Skipping service worker registration, disabled by the user');
diff --git a/ui/src/frontend/sidebar.ts b/ui/src/frontend/sidebar.ts
index 3eda7a5..c2b4d2f 100644
--- a/ui/src/frontend/sidebar.ts
+++ b/ui/src/frontend/sidebar.ts
@@ -16,14 +16,14 @@
import {assertExists, assertTrue} from '../base/logging';
import {Actions} from '../common/actions';
+import {getCurrentChannel} from '../common/channels';
import {TRACE_SUFFIX} from '../common/constants';
import {ConversionJobStatus} from '../common/conversion_jobs';
-import {QueryResponse} from '../common/queries';
import {EngineMode, TraceArrayBufferSource} from '../common/state';
import * as version from '../gen/perfetto_version';
import {Animation} from './animation';
-import {copyToClipboard} from './clipboard';
+import {onClickCopy} from './clipboard';
import {globals} from './globals';
import {toggleHelp} from './help_modal';
import {
@@ -31,7 +31,13 @@
openFileWithLegacyTraceViewer,
} from './legacy_trace_viewer';
import {showModal} from './modal';
+import {Router} from './router';
import {isDownloadable, isShareable} from './trace_attrs';
+import {
+ convertToJson,
+ convertTraceToJsonAndDownload,
+ convertTraceToSystraceAndDownload
+} from './trace_converter';
const ALL_PROCESSES_QUERY = 'select name, pid from process order by name;';
@@ -99,6 +105,9 @@
from sqlstats, first
order by started desc`;
+const GITILES_URL =
+ 'https://android.googlesource.com/platform/external/perfetto';
+
let lastTabTitle = '';
function createCannedQuery(query: string): (_: Event) => void {
@@ -301,6 +310,7 @@
a: 'https://perfetto.dev',
i: 'find_in_page',
},
+ {t: 'Flags', a: navigateFlags, i: 'emoji_flags'},
{
t: 'Report a bug',
a: 'https://goto.google.com/perfetto-ui-bug',
@@ -311,34 +321,24 @@
];
-const vidSection = {
- title: 'Video',
- summary: 'Open a screen recording',
- expanded: true,
- items: [
- {t: 'Open video file', a: popupVideoSelectionDialog, i: 'folder_open'},
- ],
-};
-
function openHelp(e: Event) {
e.preventDefault();
toggleHelp();
}
function getFileElement(): HTMLInputElement {
- return document.querySelector('input[type=file]')! as HTMLInputElement;
+ return assertExists(
+ document.querySelector<HTMLInputElement>('input[type=file]'));
}
function popupFileSelectionDialog(e: Event) {
e.preventDefault();
delete getFileElement().dataset['useCatapultLegacyUi'];
- delete getFileElement().dataset['video'];
getFileElement().click();
}
function popupFileSelectionDialogOldUI(e: Event) {
e.preventDefault();
- delete getFileElement().dataset['video'];
getFileElement().dataset['useCatapultLegacyUi'] = '1';
getFileElement().click();
}
@@ -365,7 +365,7 @@
});
}
-async function getCurrentTrace(): Promise<Blob> {
+export async function getCurrentTrace(): Promise<Blob> {
// Caller must check engine exists.
const engine = assertExists(Object.values(globals.state.engines)[0]);
const src = engine.source;
@@ -401,7 +401,7 @@
if (!isTraceLoaded) return;
getCurrentTrace()
.then(file => {
- globals.dispatch(Actions.convertTraceToSystraceAndDownload({file}));
+ convertTraceToSystraceAndDownload(file);
})
.catch(error => {
throw new Error(`Failed to get current trace ${error}`);
@@ -415,7 +415,7 @@
if (!isTraceLoaded) return;
getCurrentTrace()
.then(file => {
- globals.dispatch(Actions.convertTraceToJsonAndDownload({file}));
+ convertTraceToJsonAndDownload(file);
})
.catch(error => {
throw new Error(`Failed to get current trace ${error}`);
@@ -427,18 +427,10 @@
return engine !== undefined;
}
-function popupVideoSelectionDialog(e: Event) {
- e.preventDefault();
- delete getFileElement().dataset['useCatapultLegacyUi'];
- getFileElement().dataset['video'] = '1';
- getFileElement().click();
-}
-
function openTraceUrl(url: string): (e: Event) => void {
return e => {
globals.logging.logEvent('Trace Actions', 'Open example trace');
e.preventDefault();
- globals.frontendLocalState.localOnlyMode = false;
globals.dispatch(Actions.openTraceFromUrl({url}));
};
}
@@ -452,34 +444,11 @@
// Reset the value so onchange will be fired with the same file.
e.target.value = '';
- globals.frontendLocalState.localOnlyMode = false;
-
if (e.target.dataset['useCatapultLegacyUi'] === '1') {
openWithLegacyUi(file);
return;
}
- if (e.target.dataset['video'] === '1') {
- // TODO(hjd): Update this to use a controller and publish.
- globals.dispatch(Actions.executeQuery({
- engineId: '0', queryId: 'command',
- query: `select ts from slices where name = 'first_frame' union ` +
- `select start_ts from trace_bounds`}));
- setTimeout(() => {
- const resp = globals.queryResults.get('command') as QueryResponse;
- // First value is screenrecord trace event timestamp
- // and second value is trace boundary's start timestamp
- const offset = (Number(resp.rows[1]['ts'].toString()) -
- Number(resp.rows[0]['ts'].toString())) /
- 1e9;
- globals.queryResults.delete('command');
- globals.rafScheduler.scheduleFullRedraw();
- globals.dispatch(Actions.deleteQuery({queryId: 'command'}));
- globals.dispatch(Actions.setVideoOffset({offset}));
- }, 1000);
- globals.dispatch(Actions.openVideoFromFile({file}));
- return;
- }
globals.logging.logEvent('Trace Actions', 'Open trace from file');
globals.dispatch(Actions.openTraceFromFile({file}));
}
@@ -497,7 +466,7 @@
function openInOldUIWithSizeCheck(trace: Blob) {
// Perfetto traces smaller than 50mb can be safely opened in the legacy UI.
if (trace.size < 1024 * 1024 * 50) {
- globals.dispatch(Actions.convertTraceToJson({file: trace}));
+ convertToJson(trace);
return;
}
@@ -525,7 +494,7 @@
primary: false,
id: 'open',
action: () => {
- globals.dispatch(Actions.convertTraceToJson({file: trace}));
+ convertToJson(trace);
}
},
{
@@ -533,8 +502,7 @@
primary: true,
id: 'truncate-start',
action: () => {
- globals.dispatch(
- Actions.convertTraceToJson({file: trace, truncate: 'start'}));
+ convertToJson(trace, /*truncate*/ 'start');
}
},
{
@@ -542,8 +510,7 @@
primary: true,
id: 'truncate-end',
action: () => {
- globals.dispatch(
- Actions.convertTraceToJson({file: trace, truncate: 'end'}));
+ convertToJson(trace, /*truncate*/ 'end');
}
}
@@ -554,27 +521,32 @@
function navigateRecord(e: Event) {
e.preventDefault();
- globals.dispatch(Actions.navigate({route: '/record'}));
+ Router.navigate('#!/record');
}
function navigateAnalyze(e: Event) {
e.preventDefault();
- globals.dispatch(Actions.navigate({route: '/query'}));
+ Router.navigate('#!/query');
+}
+
+function navigateFlags(e: Event) {
+ e.preventDefault();
+ Router.navigate('#!/flags');
}
function navigateMetrics(e: Event) {
e.preventDefault();
- globals.dispatch(Actions.navigate({route: '/metrics'}));
+ Router.navigate('#!/metrics');
}
function navigateInfo(e: Event) {
e.preventDefault();
- globals.dispatch(Actions.navigate({route: '/info'}));
+ Router.navigate('#!/info');
}
function navigateViewer(e: Event) {
e.preventDefault();
- globals.dispatch(Actions.navigate({route: '/viewer'}));
+ Router.navigate('#!/viewer');
}
function shareTrace(e: Event) {
@@ -781,7 +753,7 @@
'.sidebar-footer',
m('button',
{
- onclick: () => globals.frontendLocalState.togglePerfDebug(),
+ onclick: () => globals.dispatch(Actions.togglePerfDebug({})),
},
m('i.material-icons',
{title: 'Toggle Perf Debug Mode'},
@@ -792,12 +764,11 @@
'.version',
m('a',
{
- href: `https://github.com/google/perfetto/tree/${
- version.SCM_REVISION}/ui`,
- title: `Channel: ${globals.channel}`,
+ href: `${GITILES_URL}/+/${version.SCM_REVISION}/ui`,
+ title: `Channel: ${getCurrentChannel()}`,
target: '_blank',
},
- `${version.VERSION}`),
+ `${version.VERSION.substr(0, 11)}`),
),
);
}
@@ -892,59 +863,32 @@
m('h2', section.summary)),
m('.section-content', m('ul', vdomItems))));
}
- if (globals.state.videoEnabled) {
- const videoVdomItems = [];
- for (const item of vidSection.items) {
- videoVdomItems.push(
- m('li',
- m(`a`,
- {
- onclick: typeof item.a === 'function' ? item.a : null,
- href: typeof item.a === 'string' ? item.a : '#',
- },
- m('i.material-icons', item.i),
- item.t)));
- }
- vdomSections.push(
- m(`section${vidSection.expanded ? '.expanded' : ''}`,
- m('.section-header',
- {
- onclick: () => {
- vidSection.expanded = !vidSection.expanded;
- globals.rafScheduler.scheduleFullRedraw();
- }
- },
- m('h1', vidSection.title),
- m('h2', vidSection.summary), ),
- m('.section-content', m('ul', videoVdomItems))));
- }
return m(
'nav.sidebar',
{
- class: globals.frontendLocalState.sidebarVisible ? 'show-sidebar' :
- 'hide-sidebar',
+ class: globals.state.sidebarVisible ? 'show-sidebar' : 'hide-sidebar',
// 150 here matches --sidebar-timing in the css.
ontransitionstart: () => this._redrawWhileAnimating.start(150),
ontransitionend: () => this._redrawWhileAnimating.stop(),
},
m(
- `header.${globals.channel}`,
+ `header.${getCurrentChannel()}`,
m(`img[src=${globals.root}assets/brand.png].brand`),
m('button.sidebar-button',
{
onclick: () => {
- globals.frontendLocalState.toggleSidebar();
+ globals.dispatch(Actions.toggleSidebar({}));
},
},
m('i.material-icons',
{
- title: globals.frontendLocalState.sidebarVisible ?
- 'Hide menu' :
- 'Show menu',
+ title: globals.state.sidebarVisible ? 'Hide menu' :
+ 'Show menu',
},
'menu')),
),
- m('input[type=file]', {onchange: onInputElementFileSelectionChanged}),
+ m('input.trace_file[type=file]',
+ {onchange: onInputElementFileSelectionChanged}),
m('.sidebar-scroll',
m(
'.sidebar-scroll-container',
@@ -963,14 +907,7 @@
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,
- }));
- },
+ onclick: onClickCopy(url)
};
return m('a.trace-file-name', linkProps, title);
}
diff --git a/ui/src/frontend/tickmark_panel.ts b/ui/src/frontend/tickmark_panel.ts
index 32fa051..6cc8037 100644
--- a/ui/src/frontend/tickmark_panel.ts
+++ b/ui/src/frontend/tickmark_panel.ts
@@ -53,7 +53,7 @@
Math.ceil(rectEnd - rectStart),
size.height);
}
- const index = globals.frontendLocalState.searchIndex;
+ const index = globals.state.searchIndex;
const startSec = fromNs(globals.currentSearchResults.tsStarts[index]);
const triangleStart =
Math.max(timeScale.timeToPx(startSec), 0) + TRACK_SHELL_WIDTH;
diff --git a/ui/src/frontend/time_selection_panel.ts b/ui/src/frontend/time_selection_panel.ts
index 8ec0748..65ac83e 100644
--- a/ui/src/frontend/time_selection_panel.ts
+++ b/ui/src/frontend/time_selection_panel.ts
@@ -142,9 +142,8 @@
this.renderSpan(ctx, size, new TimeSpan(start, end));
}
- if (globals.frontendLocalState.hoveredLogsTimestamp !== -1) {
- this.renderHover(
- ctx, size, globals.frontendLocalState.hoveredLogsTimestamp);
+ if (globals.state.hoveredLogsTimestamp !== -1) {
+ this.renderHover(ctx, size, globals.state.hoveredLogsTimestamp);
}
for (const note of Object.values(globals.state.notes)) {
diff --git a/ui/src/frontend/topbar.ts b/ui/src/frontend/topbar.ts
index 1f9d351..9cb29bf 100644
--- a/ui/src/frontend/topbar.ts
+++ b/ui/src/frontend/topbar.ts
@@ -107,7 +107,6 @@
}
const commandMode = mode === COMMAND;
- const state = globals.frontendLocalState;
return m(
`.omnibox${commandMode ? '.command-mode' : ''}`,
m('input', {
@@ -117,9 +116,8 @@
globals.frontendLocalState.setOmnibox(
value, commandMode ? 'COMMAND' : 'SEARCH');
if (mode === SEARCH) {
- globals.frontendLocalState.setSearchIndex(-1);
displayStepThrough = value.length >= 4;
- globals.rafScheduler.scheduleFullRedraw();
+ globals.dispatch(Actions.setSearchIndex({index: -1}));
}
},
value: globals.frontendLocalState.omnibox,
@@ -131,11 +129,11 @@
`${
globals.currentSearchResults.totalResults === 0 ?
'0 / 0' :
- `${state.searchIndex + 1} / ${
+ `${globals.state.searchIndex + 1} / ${
globals.currentSearchResults.totalResults}`}`),
m('button',
{
- disabled: state.searchIndex <= 0,
+ disabled: globals.state.searchIndex <= 0,
onclick: () => {
executeSearch(true /* reverse direction */);
}
@@ -143,7 +141,7 @@
m('i.material-icons.left', 'keyboard_arrow_left')),
m('button',
{
- disabled: state.searchIndex ===
+ disabled: globals.state.searchIndex ===
globals.currentSearchResults.totalResults - 1,
onclick: () => {
executeSearch();
@@ -252,9 +250,7 @@
view() {
return m(
'.topbar',
- {
- class: globals.frontendLocalState.sidebarVisible ? '' : 'hide-sidebar'
- },
+ {class: globals.state.sidebarVisible ? '' : 'hide-sidebar'},
globals.frontendLocalState.newVersionAvailable ?
m(NewVersionNotification) :
m(Omnibox),
diff --git a/ui/src/frontend/trace_attrs.ts b/ui/src/frontend/trace_attrs.ts
index 2d6ffcf..9cc7292 100644
--- a/ui/src/frontend/trace_attrs.ts
+++ b/ui/src/frontend/trace_attrs.ts
@@ -19,8 +19,11 @@
}
export function isDownloadable() {
- if (globals.frontendLocalState.localOnlyMode) return false;
const engine = Object.values(globals.state.engines)[0];
+ if (engine && engine.source.type === 'ARRAY_BUFFER' &&
+ engine.source.localOnly) {
+ return false;
+ }
if (engine && engine.source.type === 'HTTP_RPC') return false;
return true;
}
\ No newline at end of file
diff --git a/ui/src/frontend/trace_converter.ts b/ui/src/frontend/trace_converter.ts
new file mode 100644
index 0000000..237e39d
--- /dev/null
+++ b/ui/src/frontend/trace_converter.ts
@@ -0,0 +1,115 @@
+// 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 {Actions} from '../common/actions';
+import {
+ ConversionJobName,
+ ConversionJobStatus
+} from '../common/conversion_jobs';
+
+import {maybeShowErrorDialog} from './error_dialog';
+import {download} from './clipboard';
+import {globals} from './globals';
+import {openBufferWithLegacyTraceViewer} from './legacy_trace_viewer';
+
+type Args =
+ UpdateStatusArgs|UpdateJobStatusArgs|DownloadFileArgs|OpenTraceInLegacyArgs|ErrorArgs;
+
+interface UpdateStatusArgs {
+ kind: 'updateStatus';
+ status: string;
+}
+
+interface UpdateJobStatusArgs {
+ kind: 'updateJobStatus';
+ name: ConversionJobName;
+ status: ConversionJobStatus;
+}
+
+interface DownloadFileArgs {
+ kind: 'downloadFile';
+ buffer: Uint8Array;
+ name: string;
+}
+
+interface OpenTraceInLegacyArgs {
+ kind: 'openTraceInLegacy';
+ buffer: Uint8Array;
+}
+
+interface ErrorArgs {
+ kind: 'error';
+ error: string;
+}
+
+
+function handleOnMessage(msg: MessageEvent): void {
+ const args: Args = msg.data;
+ if (args.kind === 'updateStatus') {
+ globals.dispatch(Actions.updateStatus({
+ msg: args.status,
+ timestamp: Date.now() / 1000,
+ }));
+ } else if (args.kind === 'updateJobStatus') {
+ globals.setConversionJobStatus(args.name, args.status);
+ } else if (args.kind === 'downloadFile') {
+ download(new File([new Blob([args.buffer])], args.name));
+ } else if (args.kind === 'openTraceInLegacy') {
+ const str = (new TextDecoder('utf-8')).decode(args.buffer);
+ openBufferWithLegacyTraceViewer('trace.json', str, 0);
+ } else if (args.kind === 'error') {
+ maybeShowErrorDialog(args.error);
+ } else {
+ throw new Error(`Unhandled message ${JSON.stringify(args)}`);
+ }
+}
+
+function makeWorkerAndPost(msg: unknown) {
+ const worker = new Worker(globals.root + 'traceconv_bundle.js');
+ worker.onmessage = handleOnMessage;
+ worker.postMessage(msg);
+}
+
+export function convertTraceToJsonAndDownload(trace: Blob) {
+ makeWorkerAndPost({
+ kind: 'ConvertTraceAndDownload',
+ trace,
+ format: 'json',
+ });
+}
+
+export function convertTraceToSystraceAndDownload(trace: Blob) {
+ makeWorkerAndPost({
+ kind: 'ConvertTraceAndDownload',
+ trace,
+ format: 'systrace',
+ });
+}
+
+export function convertToJson(trace: Blob, truncate?: 'start'|'end') {
+ makeWorkerAndPost({
+ kind: 'ConvertTraceAndOpenInLegacy',
+ trace,
+ truncate,
+ });
+}
+
+export function convertTraceToPprofAndDownload(trace: Blob, pid: number, ts: number) {
+ makeWorkerAndPost({
+ kind: 'ConvertTraceToPprof',
+ trace,
+ pid,
+ ts,
+ });
+}
diff --git a/ui/src/frontend/trace_url_handler.ts b/ui/src/frontend/trace_url_handler.ts
new file mode 100644
index 0000000..fcd464d
--- /dev/null
+++ b/ui/src/frontend/trace_url_handler.ts
@@ -0,0 +1,238 @@
+// 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 * as m from 'mithril';
+
+import {Actions} from '../common/actions';
+import {tryGetTrace} from '../common/cache_manager';
+
+import {loadAndroidBugToolInfo} from './android_bug_tool';
+import {globals} from './globals';
+import {showModal} from './modal';
+import {Route, Router} from './router';
+import {taskTracker} from './task_tracker';
+
+
+export function maybeOpenTraceFromRoute(route: Route) {
+ if (route.args.s) {
+ // /?s=xxxx for permalinks.
+ globals.dispatch(Actions.loadPermalink({hash: route.args.s}));
+ return;
+ }
+
+ if (route.args.url) {
+ // /?url=https://commondatastorage.googleapis.com/bucket/trace
+ // This really works only for GCS because the Content Security Policy
+ // forbids any other url.
+ loadTraceFromUrl(route.args.url);
+ return;
+ }
+
+ if (route.args.openFromAndroidBugTool) {
+ // Handles interaction with the Android Bug Tool extension. See b/163421158.
+ openTraceFromAndroidBugTool();
+ return;
+ }
+
+ if (route.args.p && route.page === '/record') {
+ // Handles backwards compatibility for old URLs (linked from various docs),
+ // generated before we switched URL scheme. e.g., 'record?p=power' vs
+ // 'record/power'. See b/191255021#comment2.
+ Router.navigate(`#!/record/${route.args.p}`);
+ return;
+ }
+
+ if (route.args.trace_id) {
+ // Handles the case of loading traces from the cache storage.
+ maybeOpenCachedTrace(route.args.trace_id);
+ return;
+ }
+}
+
+
+/*
+ * openCachedTrace(uuid) is called: (1) on startup, from frontend/index.ts; (2)
+ * every time the fragment changes (from Router.onRouteChange).
+ * This function must be idempotent (imagine this is called on every frame).
+ * It must take decision based on the app state, not on URL change events.
+ * Fragment changes are handled by the union of Router.onHashChange() and this
+ * function, as follows:
+ * 1. '' -> URL without a ?trace_id=xxx arg:
+ * - no effect (except redrawing)
+ * 2. URL without trace_id -> URL with trace_id:
+ * - Load cached trace (without prompting any dialog).
+ * - Show a (graceful) error dialog in the case of cache misses.
+ * 3. '' -> URL with a ?trace_id=xxx arg:
+ * - Same as case 2.
+ * 4. URL with trace_id=1 -> URL with trace_id=2:
+ * a) If 2 != uuid of the trace currently loaded (globals.state.traceUuid):
+ * - Ask the user if they intend to switch trace and load 2.
+ * b) If 2 == uuid of current trace (e.g., after a new trace has loaded):
+ * - no effect (except redrawing).
+ * 5. URL with trace_id -> URL without trace_id:
+ * - Redirect to ?trace_id=1234 where 1234 is the UUID of the previous URL
+ * (this might or might not match globals.state.traceUuid).
+ *
+ * Backward navigation cases:
+ * 6. URL without trace_id <- URL with trace_id:
+ * - Same as case 5.
+ * 7. URL with trace_id=1 <- URL with trace_id=2:
+ * - Same as case 4a: go back to trace_id=1 but ask the user for confirmation.
+ * 8. landing page <- URL with trace_id:
+ * - Same as case 5: re-append the trace_id.
+ */
+async function maybeOpenCachedTrace(traceUuid: string) {
+ if (traceUuid === globals.state.traceUuid) {
+ // Do nothing, matches the currently loaded trace.
+ return;
+ }
+
+ if (traceUuid === '') {
+ // This can happen if we switch from an empty UI state to an invalid UUID
+ // (e.g. due to a cache miss, below). This can also happen if the user just
+ // types /#!/viewer?trace_id=.
+ return;
+ }
+
+ // This handles the case when a trace T1 is loaded and then the url is set to
+ // ?trace_id=T2. In that case the globals.state.traceUuid remains set to T1
+ // until T2 has been loaded by the trace processor (can take several seconds).
+ // This early out prevents to re-trigger the openTraceFromXXX() action if the
+ // URL changes (e.g. if the user navigates back/fwd) while the new trace is
+ // being loaded.
+ for (const eng of Object.values(globals.state.engines)) {
+ if (eng.source.type === 'ARRAY_BUFFER' && eng.source.uuid === traceUuid) {
+ return;
+ }
+ }
+
+ // Fetch the trace from the cache storage. If available load it. If not, show
+ // a dialog informing the user about the cache miss.
+ const maybeTrace = await tryGetTrace(traceUuid);
+
+ const navigateToOldTraceUuid = () => {
+ Router.navigate(`#!/viewer?trace_id=${globals.state.traceUuid || ''}`);
+ };
+
+ if (!maybeTrace) {
+ showModal({
+ title: 'Could not find the trace in the cache storage',
+ content: m(
+ 'div',
+ m('p',
+ 'You are trying to load a cached trace by setting the ?trace_id ' +
+ 'argument in the URL.'),
+ m('p', 'Unfortunately the trace wasn\'t in the cache storage.'),
+ m('p',
+ 'This can happen if a tab was discarded and wasn\'t opened ' +
+ 'for too long, or if you just mis-pasted the URL.'),
+ m('pre', `Trace UUID: ${traceUuid}`),
+ ),
+ buttons: [],
+ });
+ navigateToOldTraceUuid();
+ return;
+ }
+
+ // If the UI is in a blank state (no trace has been ever opened), just load
+ // the trace without showing any further dialog. This is the case of tab
+ // discarding, reloading or pasting a url with a trace_id in an empty
+ // instance.
+ if (globals.state.traceUuid === undefined) {
+ globals.dispatch(Actions.openTraceFromBuffer(maybeTrace));
+ return;
+ }
+
+ // If, instead, another trace is loaded, ask confirmation to the user.
+ // Switching to another trace clears the UI state. It can be quite annoying to
+ // lose the UI state by accidentally navigating back too much.
+ let hasOpenedNewTrace = false;
+
+ await showModal({
+ title: 'You are about to load a different trace and reset the UI state',
+ content: m(
+ 'div',
+ m('p',
+ 'You are seeing this because you either pasted a URL with ' +
+ 'a different ?trace_id=xxx argument or because you hit ' +
+ 'the history back/fwd button and reached a different trace.'),
+ m('p',
+ 'If you continue another trace will be loaded and the UI ' +
+ 'state will be cleared.'),
+ m('pre',
+ `Old trace: ${globals.state.traceUuid || '<no trace>'}\n` +
+ `New trace: ${traceUuid}`),
+ ),
+ buttons: [
+ {
+ text: 'Continue',
+ primary: true,
+ id: 'trace_id_open',
+ action: () => {
+ hasOpenedNewTrace = true;
+ globals.dispatch(Actions.openTraceFromBuffer(maybeTrace));
+ }
+ },
+ {text: 'Cancel', primary: false, id: 'trace_id_cancel', action: () => {}},
+ ],
+ });
+
+ if (!hasOpenedNewTrace) {
+ // We handle this after the modal await rather than in the cancel button
+ // action so this has effect even if the user clicks Esc or clicks outside
+ // of the modal dialog and dismisses it.
+ navigateToOldTraceUuid();
+ }
+}
+
+function loadTraceFromUrl(url: string) {
+ const isLocalhostTraceUrl =
+ ['127.0.0.1', 'localhost'].includes((new URL(url)).hostname);
+
+ if (isLocalhostTraceUrl) {
+ // This handles the special case of tools/record_android_trace serving the
+ // traces from a local webserver and killing it immediately after having
+ // seen the HTTP GET request. In those cases store the trace as a file, so
+ // when users click on share we don't fail the re-fetch().
+ const fileName = url.split('/').pop() || 'local_trace.pftrace';
+ const request = fetch(url)
+ .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}));
+ }
+}
+
+function openTraceFromAndroidBugTool() {
+ // 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);
+ });
+}
diff --git a/ui/src/frontend/track.ts b/ui/src/frontend/track.ts
index 2f491ae..fdef99b 100644
--- a/ui/src/frontend/track.ts
+++ b/ui/src/frontend/track.ts
@@ -13,6 +13,7 @@
// limitations under the License.
import * as m from 'mithril';
+import {assertExists} from '../base/logging';
import {TrackState} from '../common/state';
import {TrackData} from '../common/track_data';
import {checkerboard} from './checkerboard';
@@ -21,6 +22,13 @@
import {TrackButtonAttrs} from './track_panel';
/**
+ * Args passed to the track constructors when creating a new track.
+ */
+export interface NewTrackArgs {
+ trackId: string;
+}
+
+/**
* This interface forces track implementations to have some static properties.
* Typescript does not have abstract static members, which is why this needs to
* be in a separate interface.
@@ -30,9 +38,9 @@
// case we ever minify our code.
readonly kind: string;
- // We need the |create| method because the stored value in the registry is an
- // abstract class, and we cannot call 'new' on an abstract class.
- create(TrackState: TrackState): Track;
+ // We need the |create| method because the stored value in the registry can be
+ // an abstract class, and we cannot call 'new' on an abstract class.
+ create(args: NewTrackArgs): Track;
}
export interface SliceRect {
@@ -47,18 +55,37 @@
* The abstract class that needs to be implemented by all tracks.
*/
export abstract class Track<Config = {}, Data extends TrackData = TrackData> {
+ // The UI-generated track ID (not to be confused with the SQL track.id).
private trackId: string;
- constructor(trackState: TrackState) {
- this.trackId = trackState.id;
+
+ // Caches the last state.track[this.trackId]. This is to deal with track
+ // deletion, see comments in trackState() below.
+ private lastTrackState: TrackState;
+
+ constructor(args: NewTrackArgs) {
+ this.trackId = args.trackId;
+ this.lastTrackState = assertExists(globals.state.tracks[this.trackId]);
}
+
protected abstract renderCanvas(ctx: CanvasRenderingContext2D): void;
protected get trackState(): TrackState {
- return globals.state.tracks[this.trackId];
+ // We can end up in a state where a Track is still in the mithril renderer
+ // tree but its corresponding state has been deleted. This can happen in the
+ // interval of time between a track being removed from the state and the
+ // next animation frame that would remove the Track object. If a mouse event
+ // is dispatched in the meanwhile (or a promise is resolved), we need to be
+ // able to access the state. Hence the caching logic here.
+ const trackState = globals.state.tracks[this.trackId];
+ if (trackState === undefined) {
+ return this.lastTrackState;
+ }
+ this.lastTrackState = trackState;
+ return trackState;
}
get config(): Config {
- return globals.state.tracks[this.trackId].config as Config;
+ return this.trackState.config as Config;
}
data(): Data|undefined {
diff --git a/ui/src/frontend/track_group_panel.ts b/ui/src/frontend/track_group_panel.ts
index c65af87..2171bbf 100644
--- a/ui/src/frontend/track_group_panel.ts
+++ b/ui/src/frontend/track_group_panel.ts
@@ -55,7 +55,8 @@
super();
this.trackGroupId = attrs.trackGroupId;
const trackCreator = trackRegistry.get(this.summaryTrackState.kind);
- this.summaryTrack = trackCreator.create(this.summaryTrackState);
+ this.summaryTrack =
+ trackCreator.create({trackId: this.summaryTrackState.id});
}
get trackGroupState(): TrackGroupState {
@@ -76,10 +77,9 @@
// The shell should be highlighted if the current search result is inside
// this track group.
let highlightClass = '';
- const searchIndex = globals.frontendLocalState.searchIndex;
+ const searchIndex = globals.state.searchIndex;
if (searchIndex !== -1) {
- const trackId = globals.currentSearchResults
- .trackIds[globals.frontendLocalState.searchIndex];
+ const trackId = globals.currentSearchResults.trackIds[searchIndex];
const parentTrackId = getContainingTrackId(globals.state, trackId);
if (parentTrackId === attrs.trackGroupId) {
highlightClass = 'flash';
@@ -201,19 +201,19 @@
const localState = globals.frontendLocalState;
// Draw vertical line when hovering on the notes panel.
- if (localState.hoveredNoteTimestamp !== -1) {
+ if (globals.state.hoveredNoteTimestamp !== -1) {
drawVerticalLineAtTime(
ctx,
localState.timeScale,
- localState.hoveredNoteTimestamp,
+ globals.state.hoveredNoteTimestamp,
size.height,
`#aaa`);
}
- if (localState.hoveredLogsTimestamp !== -1) {
+ if (globals.state.hoveredLogsTimestamp !== -1) {
drawVerticalLineAtTime(
ctx,
localState.timeScale,
- localState.hoveredLogsTimestamp,
+ globals.state.hoveredLogsTimestamp,
size.height,
`#344596`);
}
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index e982f99..c89b061 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -61,10 +61,9 @@
// The shell should be highlighted if the current search result is inside
// this track.
let highlightClass = '';
- const searchIndex = globals.frontendLocalState.searchIndex;
+ const searchIndex = globals.state.searchIndex;
if (searchIndex !== -1) {
- const trackId = globals.currentSearchResults
- .trackIds[globals.frontendLocalState.searchIndex];
+ const trackId = globals.currentSearchResults.trackIds[searchIndex];
if (trackId === attrs.trackState.id) {
highlightClass = 'flash';
}
@@ -83,11 +82,15 @@
ondragleave: this.ondragleave.bind(this),
ondrop: this.ondrop.bind(this),
},
- m('h1',
- {
- title: attrs.trackState.name,
- },
- attrs.trackState.name),
+ m(
+ 'h1',
+ {
+ title: attrs.trackState.name,
+ },
+ attrs.trackState.name,
+ ('namespace' in attrs.trackState.config) &&
+ m('span.chip', 'metric'),
+ ),
m('.track-buttons',
attrs.track.getTrackShellButtons(),
m(TrackButton, {
@@ -280,9 +283,10 @@
private trackState: TrackState;
constructor(vnode: m.CVnode<TrackPanelAttrs>) {
super();
- this.trackState = globals.state.tracks[vnode.attrs.id];
+ const trackId = vnode.attrs.id;
+ this.trackState = globals.state.tracks[trackId];
const trackCreator = trackRegistry.get(this.trackState.kind);
- this.track = trackCreator.create(this.trackState);
+ this.track = trackCreator.create({trackId});
}
view() {
@@ -323,19 +327,19 @@
const localState = globals.frontendLocalState;
// Draw vertical line when hovering on the notes panel.
- if (localState.hoveredNoteTimestamp !== -1) {
+ if (globals.state.hoveredNoteTimestamp !== -1) {
drawVerticalLineAtTime(
ctx,
localState.timeScale,
- localState.hoveredNoteTimestamp,
+ globals.state.hoveredNoteTimestamp,
size.height,
`#aaa`);
}
- if (localState.hoveredLogsTimestamp !== -1) {
+ if (globals.state.hoveredLogsTimestamp !== -1) {
drawVerticalLineAtTime(
ctx,
localState.timeScale,
- localState.hoveredLogsTimestamp,
+ globals.state.hoveredLogsTimestamp,
size.height,
`#344596`);
}
diff --git a/ui/src/frontend/video_panel.ts b/ui/src/frontend/video_panel.ts
deleted file mode 100644
index 405258c..0000000
--- a/ui/src/frontend/video_panel.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 * as m from 'mithril';
-
-import {Actions} from '../common/actions';
-import {randomColor} from '../common/colorizer';
-
-import {globals} from './globals';
-
-export class VideoPanel implements m.ClassComponent {
- view() {
- const vidSections = [];
- const offset = globals.state.traceTime.startSec + globals.state.videoOffset;
- vidSections.push(
- m('video', {
- class: 'video-panel',
- controls: true,
- width: 320,
- currentTime: globals.frontendLocalState.vidTimestamp - offset,
- onpause: (e: Event) => {
- const elem = e.target as HTMLVideoElement;
- if (globals.state.flagPauseEnabled && !(elem.ended)) {
- const timestamp = elem.currentTime + offset;
- const color = randomColor();
- const isMovie = true;
- globals.dispatch(Actions.addNote({timestamp, color, isMovie}));
- elem.currentTime = timestamp - offset;
- globals.frontendLocalState.setVidTimestamp(timestamp);
- }
- },
- ontimeupdate: (e: Event) => {
- const elem = e.target as HTMLVideoElement;
- if (globals.state.scrubbingEnabled) {
- elem.currentTime = globals.frontendLocalState.vidTimestamp - offset;
- }
- },
- },
- m('source', { src: globals.state.video, type: 'video/mp4' })));
- const vidMessages = [];
- const pSetting = `Pause/Flag Synchronization: `;
- const pEnabled = `When you pause the video, a video flag ` +
- `will be drawn at this position. \n Also, adding a video flag by ` +
- `clicking on the notes panel (below the time axis) will move the video ` +
- `to this position.`;
- const pDisabled = `Press 'p' to enable.`;
- const tSetting = `Timeline Scrubbing: `;
- const tEnabled = `When you hover over the notes panel, the video will ` +
- `skip to the hovered timestamp.`;
- const tDisabled = `Press 't' to enable.`;
- function makeMsg(setting: boolean, msgType: string, e: string, d: string) {
- return m('h1', { class: `video-panel-${msgType}` }, setting ? e : d);
- }
- vidMessages.push(
- makeMsg(globals.state.flagPauseEnabled, 'setting',
- pSetting.concat('Enabled'), pSetting.concat('Disabled')),
- makeMsg(globals.state.flagPauseEnabled, 'message', pEnabled, pDisabled),
- makeMsg(globals.state.scrubbingEnabled, 'setting',
- tSetting.concat('Enabled'), tSetting.concat('Disabled')),
- makeMsg(globals.state.scrubbingEnabled, 'message', tEnabled, tDisabled));
- vidSections.push(vidMessages);
- return m('.video-panel', vidSections);
- }
-}
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 2d06c70..0cce472 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -32,7 +32,6 @@
import {DISMISSED_PANNING_HINT_KEY} from './topbar';
import {TrackGroupPanel} from './track_group_panel';
import {TrackPanel} from './track_panel';
-import {VideoPanel} from './video_panel';
const SIDEBAR_WIDTH = 256;
@@ -262,11 +261,7 @@
doesScroll: true,
panels: scrollingPanels,
kind: 'TRACKS',
- }))),
- m('.video-panel',
- (globals.state.videoEnabled && globals.state.video != null) ?
- m(VideoPanel) :
- null)),
+ })))),
m(DetailsPanel));
}
}
diff --git a/ui/src/service_worker/service_worker.ts b/ui/src/service_worker/service_worker.ts
index fbe5551..b3b3476 100644
--- a/ui/src/service_worker/service_worker.ts
+++ b/ui/src/service_worker/service_worker.ts
@@ -60,11 +60,11 @@
// 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 .
+// /v1.2-sha/frontend_bundle.js.
+// - /v1.2-sha/frontend_bundle.js will register /service_worker.js?v=v1.2-sha.
// 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.
+// The reinstallation will cache the new files from the v.1.2-sha/manifest.json.
self.addEventListener('install', event => {
const doInstall = async () => {
if (await caches.has('BYPASS_SERVICE_WORKER')) {
@@ -79,20 +79,20 @@
}
}
- // The UI should register this as service_worker.js?v=v1.2.3. Extract the
+ // The UI should register this as service_worker.js?v=v1.2-sha. Extract the
// version number and pre-fetch all the contents for the version.
- const match = /\bv=([\w.]*)/.exec(location.search);
+ 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`);
+ `?v=v1.2-sha 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
+ // subresources are versioned (e.g. /v1.2-sha/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.
diff --git a/ui/src/test/example_async_unittest.ts b/ui/src/test/example_async_unittest.ts
deleted file mode 100644
index c6868c1..0000000
--- a/ui/src/test/example_async_unittest.ts
+++ /dev/null
@@ -1,18 +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.
-
-test('example async unittest', async () => {
- const result = await Promise.resolve('foo');
- expect(result).toEqual('foo');
-});
diff --git a/ui/src/test/example_dingus_unittest.ts b/ui/src/test/example_dingus_unittest.ts
deleted file mode 100644
index be42bcb..0000000
--- a/ui/src/test/example_dingus_unittest.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {dingus} from 'dingusjs';
-
-interface VoidFunctionWithNumberArg {
- (_: number): void;
-}
-
-class ExampleClass {
- isEven(n: number): boolean {
- return n % 2 === 0;
- }
-}
-
-function* evenNumbers(n: number, math: ExampleClass) {
- for (let i = 0; i < n; i++) {
- if (math.isEven(i)) yield i;
- }
-}
-
-/**
- * Call |f| |n| times (once with each number [0, n)).
- */
-function iterMap(f: VoidFunctionWithNumberArg, n: number): void {
- for (let i = 0; i < n; i++) {
- f(i);
- }
-}
-
-test('example dingus test', () => {
- const d = dingus<VoidFunctionWithNumberArg>();
- iterMap(d, 3);
- expect(d.calls.length).toBe(3);
- expect(d.calls.filter(([_a, args, _b]) => args[0] === 1).length).toBe(1);
-});
-
-test('example dingus test class', () => {
- const d = dingus<ExampleClass>('math');
- // Dingus returns a truthy dingus in all situations - so bear that in mind!
- expect([...evenNumbers(3, d)]).toEqual([0, 1, 2]);
-});
diff --git a/ui/src/test/example_headlesstest.ts b/ui/src/test/example_headlesstest.ts
deleted file mode 100644
index 7d71c18..0000000
--- a/ui/src/test/example_headlesstest.ts
+++ /dev/null
@@ -1,21 +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 * as puppeteer from 'puppeteer';
-
-declare var global: {__BROWSER__: puppeteer.Browser;};
-
-test('example headless test', async () => {
- const browser = global.__BROWSER__;
- await browser.newPage();
-});
diff --git a/ui/src/test/example_jsdomtest.ts b/ui/src/test/example_jsdomtest.ts
deleted file mode 100644
index e8fd60e..0000000
--- a/ui/src/test/example_jsdomtest.ts
+++ /dev/null
@@ -1,18 +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.
-
-test('example jsdom test', () => {
- const element = document.createElement('div');
- expect(element).not.toBeNull();
-});
diff --git a/ui/src/test/example_unittest.ts b/ui/src/test/example_unittest.ts
deleted file mode 100644
index 5855f40..0000000
--- a/ui/src/test/example_unittest.ts
+++ /dev/null
@@ -1,17 +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.
-
-test('example unit test', () => {
- expect(1 + 1).toBe(2);
-});
diff --git a/ui/src/test/perfetto_ui_test_helper.ts b/ui/src/test/perfetto_ui_test_helper.ts
new file mode 100644
index 0000000..0417892
--- /dev/null
+++ b/ui/src/test/perfetto_ui_test_helper.ts
@@ -0,0 +1,115 @@
+// 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 * as fs from 'fs';
+import * as net from 'net';
+import * as libpng from 'node-libpng';
+import * as path from 'path';
+import * as pixelmatch from 'pixelmatch';
+import * as puppeteer from 'puppeteer';
+
+// These constants have been hand selected by comparing the diffs of screenshots
+// between Linux on Mac. Unfortunately font-rendering is platform-specific.
+// Even though we force the same antialiasing and hinting settings, some minimal
+// differences exist.
+const DIFF_PER_PIXEL_THRESHOLD = 0.35;
+const DIFF_MAX_PIXELS = 50;
+
+// Waits for the Perfetto UI to be quiescent, using a union of heuristics:
+// - Check that the progress bar is not animating.
+// - Check that the omnibox is not showing a message.
+// - Check that no redraws are pending in our RAF scheduler.
+// - Check that all the above is satisfied for |minIdleMs| consecutive ms.
+export async function waitForPerfettoIdle(
+ page: puppeteer.Page, minIdleMs?: number) {
+ minIdleMs = minIdleMs || 3000;
+ const tickMs = 250;
+ const timeoutMs = 30000;
+ const minIdleTicks = Math.ceil(minIdleMs / tickMs);
+ const timeoutTicks = Math.ceil(timeoutMs / tickMs);
+ let consecutiveIdleTicks = 0;
+ for (let ticks = 0; ticks < timeoutTicks; ticks++) {
+ await new Promise(r => setTimeout(r, tickMs));
+ const isShowingMsg = !!(await page.$('.omnibox.message-mode'));
+ const isShowingAnim = !!(await page.$('.progress.progress-anim'));
+ const hasPendingRedraws =
+ await (
+ await page.evaluateHandle('globals.rafScheduler.hasPendingRedraws'))
+ .jsonValue<number>();
+
+ if (isShowingAnim || isShowingMsg || hasPendingRedraws) {
+ consecutiveIdleTicks = 0;
+ continue;
+ }
+ if (++consecutiveIdleTicks >= minIdleTicks) {
+ return;
+ }
+ }
+ throw new Error(
+ `waitForPerfettoIdle() failed. Did not reach idle after ${timeoutMs} ms`);
+}
+
+export function getTestTracePath(fname: string): string {
+ const fPath = path.join('test', 'data', fname);
+ if (!fs.existsSync(fPath)) {
+ throw new Error('Could not locate trace file ' + fPath);
+ }
+ return fPath;
+}
+
+export async function compareScreenshots(
+ actualFilename: string, expectedFilename: string) {
+ if (!fs.existsSync(expectedFilename)) {
+ throw new Error(
+ `Could not find ${expectedFilename}. Run wih REBASELINE=1.`);
+ }
+ const actualImg = await libpng.readPngFile(actualFilename);
+ const expectedImg = await libpng.readPngFile(expectedFilename);
+ const {width, height} = actualImg;
+ expect(width).toEqual(expectedImg.width);
+ expect(height).toEqual(expectedImg.height);
+ const diffBuff = Buffer.alloc(actualImg.data.byteLength);
+ const diff = await pixelmatch(
+ actualImg.data, expectedImg.data, diffBuff, width, height, {
+ threshold: DIFF_PER_PIXEL_THRESHOLD
+ });
+ if (diff > DIFF_MAX_PIXELS) {
+ const diffFilename = actualFilename.replace('.png', '-diff.png');
+ libpng.writePngFile(diffFilename, diffBuff, {width, height});
+ fail(`Diff test failed on ${diffFilename}, delta: ${diff} pixels`);
+ }
+ return diff;
+}
+
+
+// If the user has a trace_processor_shell --httpd instance open, bail out,
+// as that will invalidate the test loading different data.
+export async function failIfTraceProcessorHttpdIsActive() {
+ return new Promise<void>((resolve, reject) => {
+ const client = new net.Socket();
+ client.connect(9001, '127.0.0.1', () => {
+ const err = 'trace_processor_shell --httpd detected on port 9001. ' +
+ 'Bailing out as it interferes with the tests. ' +
+ 'Please kill that and run the test again.';
+ console.error(err);
+ client.destroy();
+ reject(err);
+ });
+ client.on('error', (e: {code: string}) => {
+ expect(e.code).toBe('ECONNREFUSED');
+ resolve();
+ });
+ client.end();
+ });
+}
diff --git a/ui/src/test/ui_integrationtest.ts b/ui/src/test/ui_integrationtest.ts
new file mode 100644
index 0000000..6bf5c3f
--- /dev/null
+++ b/ui/src/test/ui_integrationtest.ts
@@ -0,0 +1,282 @@
+// 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 * as fs from 'fs';
+import * as path from 'path';
+import * as puppeteer from 'puppeteer';
+
+import {assertExists} from '../base/logging';
+
+import {
+ compareScreenshots,
+ failIfTraceProcessorHttpdIsActive,
+ getTestTracePath,
+ waitForPerfettoIdle
+} from './perfetto_ui_test_helper';
+
+declare var global: {__BROWSER__: puppeteer.Browser;};
+const browser = assertExists(global.__BROWSER__);
+const expectedScreenshotPath = path.join('test', 'data', 'ui-screenshots');
+
+async function getPage(): Promise<puppeteer.Page> {
+ const pages = (await browser.pages());
+ expect(pages.length).toBe(1);
+ return pages[pages.length - 1];
+}
+
+// Executed once at the beginning of the test. Navigates to the UI.
+beforeAll(async () => {
+ await failIfTraceProcessorHttpdIsActive();
+ jest.setTimeout(60000);
+ const page = await getPage();
+ await page.setViewport({width: 1920, height: 1080});
+});
+
+// After each test (regardless of nesting) capture a screenshot named after the
+// test('') name and compare the screenshot with the expected one in
+// /test/data/ui-screenshots.
+afterEach(async () => {
+ let testName = expect.getState().currentTestName;
+ testName = testName.replace(/[^a-z0-9-]/gmi, '_').toLowerCase();
+ const page = await getPage();
+
+ // cwd() is set to //out/ui when running tests, just create a subdir in there.
+ // The CI picks up this directory and uploads to GCS after every failed run.
+ const tmpDir = path.resolve('./ui-test-artifacts');
+ if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir);
+ const screenshotName = `ui-${testName}.png`;
+ const actualFilename = path.join(tmpDir, screenshotName);
+ const expectedFilename = path.join(expectedScreenshotPath, screenshotName);
+ await page.screenshot({path: actualFilename});
+ const rebaseline = process.env['PERFETTO_UI_TESTS_REBASELINE'] === '1';
+ if (rebaseline) {
+ console.log('Saving reference screenshot into', expectedFilename);
+ fs.copyFileSync(actualFilename, expectedFilename);
+ } else {
+ await compareScreenshots(actualFilename, expectedFilename);
+ }
+});
+
+describe('android_trace_30s', () => {
+ let page: puppeteer.Page;
+
+ beforeAll(async () => {
+ page = await getPage();
+ await page.goto('http://localhost:10000/?testing=1');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('load', async () => {
+ const file = await page.waitForSelector('input.trace_file');
+ const tracePath = getTestTracePath('example_android_trace_30s.pb');
+ assertExists(file).uploadFile(tracePath);
+ await waitForPerfettoIdle(page);
+ });
+
+ test('expand_camera', async () => {
+ await page.click('.main-canvas');
+ await page.click('h1[title="com.google.android.GoogleCamera 5506"]');
+ await page.evaluate(() => {
+ document.querySelector('.scrolling-panel-container')!.scrollTo(0, 400);
+ });
+ await waitForPerfettoIdle(page);
+ });
+
+ // TODO(198431341): Test is flaky. We should de-flake and re-enable.
+ // test('search', async () => {
+ // const page = await getPage();
+ // const searchInput = '.omnibox input';
+ // await page.focus(searchInput);
+ // await page.keyboard.type('TrimMaps');
+ // await waitForPerfettoIdle(page);
+ // for (let i = 0; i < 10; i++) {
+ // await page.keyboard.type('\n');
+ // }
+ // await waitForPerfettoIdle(page);
+ //});
+});
+
+describe('chrome_rendering_desktop', () => {
+ let page: puppeteer.Page;
+
+ beforeAll(async () => {
+ page = await getPage();
+ await page.goto('http://localhost:10000/?testing=1');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('load', async () => {
+ const page = await getPage();
+ const file = await page.waitForSelector('input.trace_file');
+ const tracePath = getTestTracePath('chrome_rendering_desktop.pftrace');
+ assertExists(file).uploadFile(tracePath);
+ await waitForPerfettoIdle(page);
+ });
+
+ test('expand_browser_proc', async () => {
+ const page = await getPage();
+ await page.click('.main-canvas');
+ await page.click('h1[title="Browser 12685"]');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('select_slice_with_flows', async () => {
+ const page = await getPage();
+ const searchInput = '.omnibox input';
+ await page.focus(searchInput);
+ await page.keyboard.type('GenerateRenderPass');
+ await waitForPerfettoIdle(page);
+ for (let i = 0; i < 3; i++) {
+ await page.keyboard.type('\n');
+ }
+ await waitForPerfettoIdle(page);
+ await page.focus('canvas');
+ await page.keyboard.type('f'); // Zoom to selection
+ await waitForPerfettoIdle(page);
+ });
+});
+
+describe('routing', () => {
+ describe('open_two_traces_then_go_back', () => {
+ let page: puppeteer.Page;
+
+ beforeAll(async () => {
+ page = await getPage();
+ await page.goto('http://localhost:10000/?testing=1');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('open_first_trace_from_url', async () => {
+ await page.goto(
+ 'http://localhost:10000/?testing=1/#!/?url=http://localhost:10000/test/data/chrome_memory_snapshot.pftrace');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('open_second_trace_from_url', async () => {
+ await page.goto(
+ 'http://localhost:10000/?testing=1#!/?url=http://localhost:10000/test/data/chrome_scroll_without_vsync.pftrace');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('access_subpage_then_go_back', async () => {
+ await waitForPerfettoIdle(page);
+ await page.goto(
+ 'http://localhost:10000/?testing=1/#!/metrics?trace_id=76c25a80-25dd-1eb7-2246-d7b3c7a10f91');
+ await page.goBack();
+ await waitForPerfettoIdle(page);
+ });
+ });
+
+ describe('start_from_no_trace', () => {
+ let page: puppeteer.Page;
+
+ beforeAll(async () => {
+ page = await getPage();
+ await page.goto('about:blank');
+ });
+
+ test('go_to_page_with_no_trace', async () => {
+ await page.goto('http://localhost:10000/?testing=1#!/info');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('open_trace ', async () => {
+ await page.goto(
+ 'http://localhost:10000/?testing=1#!/viewer?trace_id=76c25a80-25dd-1eb7-2246-d7b3c7a10f91');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('refresh', async () => {
+ await page.reload();
+ await waitForPerfettoIdle(page);
+ });
+
+ test('open_second_trace', async () => {
+ await page.goto(
+ 'http://localhost:10000/?testing=1#!/viewer?trace_id=00000000-0000-0000-e13c-bd7db4ff646f');
+ await waitForPerfettoIdle(page);
+
+ // click on the 'Continue' button in the interstitial
+ await page.click('[id="trace_id_open"]');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('go_back_to_first_trace', async () => {
+ await page.goBack();
+ await waitForPerfettoIdle(page);
+ // click on the 'Continue' button in the interstitial
+ await page.click('[id="trace_id_open"]');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('open_invalid_trace', async () => {
+ await page.goto(
+ 'http://localhost:10000/?testing=1#!/viewer?trace_id=invalid');
+ await waitForPerfettoIdle(page);
+ });
+ });
+
+ describe('navigate', () => {
+ let page: puppeteer.Page;
+
+ beforeAll(async () => {
+ page = await getPage();
+ await page.goto('http://localhost:10000/?testing=1');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('open_trace_from_url', async () => {
+ await page.goto(
+ 'http://localhost:10000/?testing=1/#!/?url=http://localhost:10000/test/data/chrome_memory_snapshot.pftrace');
+ await waitForPerfettoIdle(page);
+ });
+
+ test('navigate_back_and_forward', async () => {
+ await page.goto(
+ 'http://localhost:10000/?testing=1#!/info?trace_id=00000000-0000-0000-e13c-bd7db4ff646f');
+ await page.goto(
+ 'http://localhost:10000/?testing=1#!/metrics?trace_id=00000000-0000-0000-e13c-bd7db4ff646f');
+ await page.goBack();
+ await waitForPerfettoIdle(page);
+ await page.goBack();
+ await waitForPerfettoIdle(page);
+ await page.goBack();
+ await waitForPerfettoIdle(page);
+ await page.goForward();
+ await waitForPerfettoIdle(page);
+ await page.goForward();
+ await waitForPerfettoIdle(page);
+ await page.goForward();
+ await waitForPerfettoIdle(page);
+ });
+ });
+
+ test('open_trace_and_go_back_to_landing_page', async () => {
+ const page = await getPage();
+ await page.goto('http://localhost:10000/?testing=1');
+ await page.goto(
+ 'http://localhost:10000/?testing=1#!/viewer?trace_id=76c25a80-25dd-1eb7-2246-d7b3c7a10f91');
+ await waitForPerfettoIdle(page);
+ await page.goBack();
+ await waitForPerfettoIdle(page);
+ });
+
+ test('open_invalid_trace_from_blank_page', async () => {
+ const page = await getPage();
+ await page.goto('about:blank');
+ await page.goto(
+ 'http://localhost:10000/?testing=1#!/viewer?trace_id=invalid');
+ await waitForPerfettoIdle(page);
+ });
+});
diff --git a/ui/src/traceconv/index.ts b/ui/src/traceconv/index.ts
new file mode 100644
index 0000000..c3f211b
--- /dev/null
+++ b/ui/src/traceconv/index.ts
@@ -0,0 +1,235 @@
+// 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 {defer} from '../base/deferred';
+import {assertExists, reportError, setErrorHandler} from '../base/logging';
+import {
+ ConversionJobName,
+ ConversionJobStatus
+} from '../common/conversion_jobs';
+import * as trace_to_text from '../gen/trace_to_text';
+
+const selfWorker = self as {} as Worker;
+
+// TODO(hjd): The trace ends up being copied too many times due to how
+// blob works. We should reduce the number of copies.
+
+type Format = 'json'|'systrace';
+type Args = ConvertTraceAndDownloadArgs|ConvertTraceAndOpenInLegacyArgs|
+ ConvertTraceToPprofArgs;
+
+function updateStatus(status: string) {
+ selfWorker.postMessage({
+ kind: 'updateStatus',
+ status,
+ });
+}
+
+function updateJobStatus(name: ConversionJobName, status: ConversionJobStatus) {
+ selfWorker.postMessage({
+ kind: 'updateJobStatus',
+ name,
+ status,
+ });
+}
+
+function downloadFile(buffer: Uint8Array, name: string) {
+ selfWorker.postMessage({
+ kind: 'downloadFile',
+ buffer,
+ name,
+ }, [buffer.buffer]);
+}
+
+function openTraceInLegacy(buffer: Uint8Array) {
+ selfWorker.postMessage({
+ kind: 'openTraceInLegacy',
+ buffer,
+ });
+}
+
+function forwardError(error: string) {
+ selfWorker.postMessage({
+ kind: 'error',
+ error,
+ });
+}
+
+function fsNodeToBuffer(fsNode: trace_to_text.FileSystemNode): Uint8Array {
+ const fileSize = assertExists(fsNode.usedBytes);
+ return new Uint8Array(fsNode.contents.buffer, 0, fileSize);
+}
+
+async function runTraceconv(trace: Blob, args: string[]) {
+ const deferredRuntimeInitialized = defer<void>();
+ const module = trace_to_text({
+ noInitialRun: true,
+ locateFile: (s: string) => s,
+ print: updateStatus,
+ printErr: updateStatus,
+ onRuntimeInitialized: () => deferredRuntimeInitialized.resolve()
+ });
+ await deferredRuntimeInitialized;
+ module.FS.mkdir('/fs');
+ module.FS.mount(
+ assertExists(module.FS.filesystems.WORKERFS),
+ {blobs: [{name: 'trace.proto', data: trace}]},
+ '/fs');
+ updateStatus('Converting trace');
+ module.callMain(args);
+ updateStatus('Trace conversion completed');
+ return module;
+}
+
+interface ConvertTraceAndDownloadArgs {
+ kind: 'ConvertTraceAndDownload';
+ trace: Blob;
+ format: Format;
+ truncate?: 'start'|'end';
+}
+
+function isConvertTraceAndDownload(msg: Args):
+ msg is ConvertTraceAndDownloadArgs {
+ if (msg.kind !== 'ConvertTraceAndDownload') {
+ return false;
+ }
+ if (msg.trace === undefined) {
+ throw new Error('ConvertTraceAndDownloadArgs missing trace');
+ }
+ if (msg.format !== 'json' && msg.format !== 'systrace') {
+ throw new Error('ConvertTraceAndDownloadArgs has bad format');
+ }
+ return true;
+}
+
+async function ConvertTraceAndDownload(
+ trace: Blob,
+ format: Format,
+ truncate?: 'start'|'end'): Promise<void> {
+ const jobName = format === 'json' ? 'convert_json' : 'convert_systrace';
+ updateJobStatus(jobName, ConversionJobStatus.InProgress);
+ const outPath = '/trace.json';
+ const args: string[] = [format];
+ if (truncate !== undefined) {
+ args.push('--truncate', truncate);
+ }
+ args.push('/fs/trace.proto', outPath);
+ try {
+ const module = await runTraceconv(trace, args);
+ const fsNode = module.FS.lookupPath(outPath).node;
+ downloadFile(fsNodeToBuffer(fsNode), `trace.${format}`);
+ module.FS.unlink(outPath);
+ } finally {
+ updateJobStatus(jobName, ConversionJobStatus.NotRunning);
+ }
+}
+
+interface ConvertTraceAndOpenInLegacyArgs {
+ kind: 'ConvertTraceAndOpenInLegacy';
+ trace: Blob;
+ truncate?: 'start'|'end';
+}
+
+function isConvertTraceAndOpenInLegacy(msg: Args):
+ msg is ConvertTraceAndOpenInLegacyArgs {
+ if (msg.kind !== 'ConvertTraceAndOpenInLegacy') {
+ return false;
+ }
+ return true;
+}
+
+async function ConvertTraceAndOpenInLegacy(
+trace: Blob, truncate?: 'start'|'end') {
+ const jobName = 'open_in_legacy';
+ updateJobStatus(jobName, ConversionJobStatus.InProgress);
+ const outPath = '/trace.json';
+ const args: string[] = ['json'];
+ if (truncate !== undefined) {
+ args.push('--truncate', truncate);
+ }
+ args.push('/fs/trace.proto', outPath);
+ try {
+ const module = await runTraceconv( trace, args);
+ const fsNode = module.FS.lookupPath(outPath).node;
+ const data = fsNode.contents.buffer;
+ const size = fsNode.usedBytes;
+ const buffer = new Uint8Array(data, 0, size);
+ openTraceInLegacy(buffer);
+ module.FS.unlink(outPath);
+ } finally {
+ updateJobStatus(jobName, ConversionJobStatus.NotRunning);
+ }
+}
+
+interface ConvertTraceToPprofArgs {
+ kind: 'ConvertTraceToPprof';
+ trace: Blob;
+ pid: number;
+ ts: number;
+}
+
+function isConvertTraceToPprof(msg: Args): msg is ConvertTraceToPprofArgs {
+ if (msg.kind !== 'ConvertTraceToPprof') {
+ return false;
+ }
+ return true;
+}
+
+async function ConvertTraceToPprof(
+trace: Blob, pid: number, ts: number) {
+ const jobName = 'convert_pprof';
+ updateJobStatus(jobName, ConversionJobStatus.InProgress);
+ const args = [
+ 'profile',
+ `--pid`,
+ `${pid}`,
+ `--timestamps`,
+ `${ts}`,
+ '/fs/trace.proto'
+ ];
+
+ try {
+ const module = await runTraceconv(trace, args);
+ 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);
+ for (let i = 0; i < heapDumpFiles.length; ++i) {
+ const heapDump = heapDumpFiles[i];
+ const fileNode =
+ module.FS.lookupPath(`/tmp/${heapDirName}/${heapDump}`).node;
+ const fileName = `/heap_dump.${i}.${pid}.pb`;
+ downloadFile(fsNodeToBuffer(fileNode), fileName);
+ }
+ } finally {
+ updateJobStatus(jobName, ConversionJobStatus.NotRunning);
+ }
+}
+
+selfWorker.onmessage = (msg: MessageEvent) => {
+ self.addEventListener('error', e => reportError(e));
+ self.addEventListener('unhandledrejection', e => reportError(e));
+ setErrorHandler((err: string) => forwardError(err));
+ const args = msg.data as Args;
+ if (isConvertTraceAndDownload(args)) {
+ ConvertTraceAndDownload(args.trace, args.format, args.truncate);
+ } else if (isConvertTraceAndOpenInLegacy(args)) {
+ ConvertTraceAndOpenInLegacy(args.trace, args.truncate);
+ } else if (isConvertTraceToPprof(args)) {
+ ConvertTraceToPprof(args.trace, args.pid, args.ts);
+ } else {
+ throw new Error(`Unknown method call ${JSON.stringify(args)}`);
+ }
+};
diff --git a/ui/src/tracks/actual_frames/controller.ts b/ui/src/tracks/actual_frames/controller.ts
index 95c9201..4920c2f 100644
--- a/ui/src/tracks/actual_frames/controller.ts
+++ b/ui/src/tracks/actual_frames/controller.ts
@@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {assertTrue} from '../../base/logging';
-import {NUM, NUM_NULL, STR} from '../../common/query_iterator';
+import {NUM, NUM_NULL, STR} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {
TrackController,
@@ -45,7 +44,7 @@
const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
if (this.maxDurNs === 0) {
- const maxDurResult = await this.queryV2(`
+ const maxDurResult = await this.query(`
select
max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
as maxDur
@@ -55,7 +54,7 @@
this.maxDurNs = maxDurResult.firstRow({maxDur: NUM_NULL}).maxDur || 0;
}
- const rawResult = await this.queryV2(`
+ const rawResult = await this.query(`
SELECT
(s.ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
s.ts as ts,
@@ -132,8 +131,6 @@
let endNsQ = Math.floor((endNs + bucketNs / 2 - 1) / bucketNs) * bucketNs;
endNsQ = Math.max(endNsQ, startNsQ + bucketNs);
- assertTrue(startNsQ !== endNsQ);
-
slices.starts[i] = fromNs(startNsQ);
slices.ends[i] = fromNs(endNsQ);
slices.depths[i] = it.layoutDepth;
diff --git a/ui/src/tracks/actual_frames/frontend.ts b/ui/src/tracks/actual_frames/frontend.ts
index 3c91598..d9b9fba 100644
--- a/ui/src/tracks/actual_frames/frontend.ts
+++ b/ui/src/tracks/actual_frames/frontend.ts
@@ -12,8 +12,7 @@
// 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 {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {ChromeSliceTrack} from '../chrome_slices/frontend';
@@ -21,8 +20,8 @@
export class ActualFramesSliceTrack extends ChromeSliceTrack {
static readonly kind = ACTUAL_FRAMES_SLICE_TRACK_KIND;
- static create(trackState: TrackState): Track {
- return new ActualFramesSliceTrack(trackState);
+ static create(args: NewTrackArgs): Track {
+ return new ActualFramesSliceTrack(args);
}
}
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/actual_frames/index.ts
similarity index 84%
rename from ui/config/headless_setup.js
rename to ui/src/tracks/actual_frames/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/actual_frames/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/all_controller.ts b/ui/src/tracks/all_controller.ts
deleted file mode 100644
index ca0b5c5..0000000
--- a/ui/src/tracks/all_controller.ts
+++ /dev/null
@@ -1,30 +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 all currently implemented tracks. After implemeting a new track, an
-// import statement for it needs to be added here.
-import './android_log/controller';
-import './chrome_slices/controller';
-import './counter/controller';
-import './heap_profile/controller';
-import './cpu_freq/controller';
-import './cpu_profile/controller';
-import './cpu_slices/controller';
-import './process_scheduling/controller';
-import './process_summary/controller';
-import './thread_state/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
deleted file mode 100644
index 6af4d22..0000000
--- a/ui/src/tracks/all_frontend.ts
+++ /dev/null
@@ -1,30 +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 all currently implemented tracks. After implemeting a new track, an
-// import statement for it needs to be added here.
-import './android_log/frontend';
-import './chrome_slices/frontend';
-import './counter/frontend';
-import './heap_profile/frontend';
-import './cpu_freq/frontend';
-import './cpu_profile/frontend';
-import './cpu_slices/frontend';
-import './process_scheduling/frontend';
-import './process_summary/frontend';
-import './thread_state/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 3f1401a..b1ca9d2 100644
--- a/ui/src/tracks/android_log/controller.ts
+++ b/ui/src/tracks/android_log/controller.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {NUM} from '../../common/query_iterator';
+import {NUM} from '../../common/query_result';
import {fromNs, toNsCeil, toNsFloor} from '../../common/time';
import {LIMIT} from '../../common/track_data';
import {
@@ -33,7 +33,7 @@
// |resolution| is in s/px the frontend wants.
const quantNs = toNsCeil(resolution);
- const queryRes = await this.queryV2(`
+ const queryRes = await this.query(`
select
cast(ts / ${quantNs} as integer) * ${quantNs} as tsQuant,
prio,
diff --git a/ui/src/tracks/android_log/frontend.ts b/ui/src/tracks/android_log/frontend.ts
index 76f3aa7..0aea2fc 100644
--- a/ui/src/tracks/android_log/frontend.ts
+++ b/ui/src/tracks/android_log/frontend.ts
@@ -12,10 +12,9 @@
// 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 {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {ANDROID_LOGS_TRACK_KIND, Config, Data} from './common';
@@ -40,12 +39,12 @@
class AndroidLogTrack extends Track<Config, Data> {
static readonly kind = ANDROID_LOGS_TRACK_KIND;
- static create(trackState: TrackState): AndroidLogTrack {
- return new AndroidLogTrack(trackState);
+ static create(args: NewTrackArgs): AndroidLogTrack {
+ return new AndroidLogTrack(args);
}
- constructor(trackState: TrackState) {
- super(trackState);
+ constructor(args: NewTrackArgs) {
+ super(args);
}
renderCanvas(ctx: CanvasRenderingContext2D): void {
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/android_log/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/android_log/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/android_log/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/async_slices/controller.ts b/ui/src/tracks/async_slices/controller.ts
index 0cfc609..fa81905 100644
--- a/ui/src/tracks/async_slices/controller.ts
+++ b/ui/src/tracks/async_slices/controller.ts
@@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {assertTrue} from '../../base/logging';
-import {NUM, NUM_NULL, STR} from '../../common/query_iterator';
+import {NUM, NUM_NULL, STR} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {
TrackController,
@@ -38,7 +37,7 @@
const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
if (this.maxDurNs === 0) {
- const maxDurResult = await this.queryV2(`
+ const maxDurResult = await this.query(`
select max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
as maxDur from experimental_slice_layout
where filter_track_ids = '${this.config.trackIds.join(',')}'
@@ -46,13 +45,13 @@
this.maxDurNs = maxDurResult.firstRow({maxDur: NUM_NULL}).maxDur || 0;
}
- const queryRes = await this.queryV2(`
+ const queryRes = 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 as depth,
- name,
+ ifnull(name, '[null]') as name,
id,
dur = 0 as isInstant,
dur = -1 as isIncomplete
@@ -61,8 +60,8 @@
filter_track_ids = '${this.config.trackIds.join(',')}' and
ts >= ${startNs - this.maxDurNs} and
ts <= ${endNs}
- group by tsq, depth
- order by tsq, depth
+ group by tsq, layout_depth
+ order by tsq, layout_depth
`);
const numRows = queryRes.numRows();
@@ -110,8 +109,6 @@
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] = it.depth;
diff --git a/ui/src/tracks/async_slices/frontend.ts b/ui/src/tracks/async_slices/frontend.ts
index 17d4d14..9f02fa1 100644
--- a/ui/src/tracks/async_slices/frontend.ts
+++ b/ui/src/tracks/async_slices/frontend.ts
@@ -12,8 +12,7 @@
// 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 {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {ChromeSliceTrack} from '../chrome_slices/frontend';
@@ -21,8 +20,8 @@
export class AsyncSliceTrack extends ChromeSliceTrack {
static readonly kind = ASYNC_SLICE_TRACK_KIND;
- static create(trackState: TrackState): Track {
- return new AsyncSliceTrack(trackState);
+ static create(args: NewTrackArgs): Track {
+ return new AsyncSliceTrack(args);
}
}
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/async_slices/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/async_slices/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/async_slices/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/chrome_slices/common.ts b/ui/src/tracks/chrome_slices/common.ts
index 41fc2f8..7b80743 100644
--- a/ui/src/tracks/chrome_slices/common.ts
+++ b/ui/src/tracks/chrome_slices/common.ts
@@ -20,6 +20,7 @@
maxDepth: number;
namespace: string;
trackId: number;
+ isThreadSlice?: boolean;
}
export interface Data extends TrackData {
@@ -33,4 +34,5 @@
colors?: Uint16Array; // Index into strings.
isInstant: Uint16Array;
isIncomplete: Uint16Array;
+ cpuTimeRatio?: Float64Array;
}
diff --git a/ui/src/tracks/chrome_slices/controller.ts b/ui/src/tracks/chrome_slices/controller.ts
index e702fd6..f0b4a63 100644
--- a/ui/src/tracks/chrome_slices/controller.ts
+++ b/ui/src/tracks/chrome_slices/controller.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {NUM, NUM_NULL, STR} from '../../common/query_iterator';
+import {NUM, NUM_NULL, STR} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {
TrackController,
@@ -36,13 +36,20 @@
// 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');
+
+ const isThreadSlice = this.config.isThreadSlice;
+ let tableName = this.namespaceTable('slice');
+ let threadDurQuery = ', dur';
+ if (isThreadSlice) {
+ tableName = this.namespaceTable('thread_slice');
+ threadDurQuery = ', iif(thread_dur IS NULL, dur, thread_dur)';
+ }
if (this.maxDurNs === 0) {
const query = `
SELECT max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
AS maxDur FROM ${tableName} WHERE track_id = ${this.config.trackId}`;
- const queryRes = await this.queryV2(query);
+ const queryRes = await this.query(query);
this.maxDurNs = queryRes.firstRow({maxDur: NUM_NULL}).maxDur || 0;
}
@@ -53,15 +60,16 @@
max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur)) as dur,
depth,
id as sliceId,
- name,
+ ifnull(name, '[null]') as name,
dur = 0 as isInstant,
dur = -1 as isIncomplete
+ ${threadDurQuery} as threadDur
FROM ${tableName}
WHERE track_id = ${this.config.trackId} AND
ts >= (${startNs - this.maxDurNs}) AND
ts <= ${endNs}
GROUP BY depth, tsq`;
- const queryRes = await this.queryV2(query);
+ const queryRes = await this.query(query);
const numRows = queryRes.numRows();
const slices: Data = {
@@ -77,6 +85,7 @@
titles: new Uint16Array(numRows),
isInstant: new Uint16Array(numRows),
isIncomplete: new Uint16Array(numRows),
+ cpuTimeRatio: new Float64Array(numRows)
};
const stringIndexes = new Map<string, number>();
@@ -97,7 +106,8 @@
sliceId: NUM,
name: STR,
isInstant: NUM,
- isIncomplete: NUM
+ isIncomplete: NUM,
+ threadDur: NUM
});
for (let row = 0; it.valid(); it.next(), row++) {
const startNsQ = it.tsq;
@@ -123,6 +133,16 @@
slices.titles[row] = internString(it.name);
slices.isInstant[row] = it.isInstant;
slices.isIncomplete[row] = it.isIncomplete;
+
+ let cpuTimeRatio = 1;
+ if (!it.isInstant && !it.isIncomplete) {
+ // Rounding the CPU time ratio to two decimal places and ensuring
+ // it is less than or equal to one, incase the thread duration exceeds
+ // the total duration.
+ cpuTimeRatio =
+ Math.min(Math.round((it.threadDur / it.dur) * 100) / 100, 1);
+ }
+ slices.cpuTimeRatio![row] = cpuTimeRatio;
}
return slices;
}
diff --git a/ui/src/tracks/chrome_slices/frontend.ts b/ui/src/tracks/chrome_slices/frontend.ts
index 403f01b..abc7129 100644
--- a/ui/src/tracks/chrome_slices/frontend.ts
+++ b/ui/src/tracks/chrome_slices/frontend.ts
@@ -16,12 +16,11 @@
import {Actions} from '../../common/actions';
import {cropText, drawIncompleteSlice} from '../../common/canvas_utils';
-import {hslForSlice} from '../../common/colorizer';
+import {hslForSlice, hslForThreadIdleSlice} from '../../common/colorizer';
import {TRACE_MARGIN_TIME_S} from '../../common/constants';
-import {TrackState} from '../../common/state';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
-import {SliceRect, Track} from '../../frontend/track';
+import {NewTrackArgs, SliceRect, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {Config, Data, SLICE_TRACK_KIND} from './common';
@@ -36,14 +35,14 @@
export class ChromeSliceTrack extends Track<Config, Data> {
static readonly kind: string = SLICE_TRACK_KIND;
- static create(trackState: TrackState): Track {
- return new ChromeSliceTrack(trackState);
+ static create(args: NewTrackArgs): Track {
+ return new ChromeSliceTrack(args);
}
private hoveredTitleId = -1;
- constructor(trackState: TrackState) {
- super(trackState);
+ constructor(args: NewTrackArgs) {
+ super(args);
}
renderCanvas(ctx: CanvasRenderingContext2D): void {
@@ -85,6 +84,7 @@
const isIncomplete = data.isIncomplete[i];
const title = data.strings[titleId];
const colorOverride = data.colors && data.strings[data.colors[i]];
+ const isThreadSlice = this.config.isThreadSlice;
if (isIncomplete) { // incomplete slice
tEnd = visibleWindowTime.end;
}
@@ -101,10 +101,11 @@
const name = title.replace(/( )?\d+/g, '');
const highlighted = titleId === this.hoveredTitleId ||
- globals.frontendLocalState.highlightedSliceId === sliceId;
+ globals.state.highlightedSliceId === sliceId;
- const [hue, saturation, lightness] =
- hslForSlice(name, highlighted || isSelected);
+ const hasFocus = highlighted || isSelected;
+
+ const [hue, saturation, lightness] = hslForSlice(name, hasFocus);
let color: string;
if (colorOverride === undefined) {
@@ -150,12 +151,28 @@
}
continue;
}
+
if (isIncomplete && rect.width > SLICE_HEIGHT / 4) {
drawIncompleteSlice(
ctx, rect.left, rect.top, rect.width, SLICE_HEIGHT, color);
+ } else if (isThreadSlice) {
+ // We draw two rectangles, representing the ratio between wall time and
+ // time spent on cpu.
+ const cpuTimeRatio = data.cpuTimeRatio![i];
+ const firstPartWidth = rect.width * cpuTimeRatio;
+ const secondPartWidth = rect.width * (1 - cpuTimeRatio);
+ ctx.fillRect(rect.left, rect.top, firstPartWidth, SLICE_HEIGHT);
+ ctx.fillStyle = hsluvToHex(
+ hslForThreadIdleSlice(hue, saturation, lightness, hasFocus));
+ ctx.fillRect(
+ rect.left + firstPartWidth,
+ rect.top,
+ secondPartWidth,
+ SLICE_HEIGHT);
} else {
ctx.fillRect(rect.left, rect.top, rect.width, SLICE_HEIGHT);
}
+
// Selected case
if (isSelected) {
drawRectOnSelected = () => {
@@ -220,18 +237,19 @@
onMouseMove({x, y}: {x: number, y: number}) {
this.hoveredTitleId = -1;
- globals.frontendLocalState.setHighlightedSliceId(-1);
+ globals.dispatch(Actions.setHighlightedSliceId({sliceId: -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 sliceId = data.sliceIds[sliceIndex];
+ globals.dispatch(Actions.setHighlightedSliceId({sliceId}));
}
onMouseOut() {
this.hoveredTitleId = -1;
- globals.frontendLocalState.setHighlightedSliceId(-1);
+ globals.dispatch(Actions.setHighlightedSliceId({sliceId: -1}));
}
onMouseClick({x, y}: {x: number, y: number}): boolean {
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/chrome_slices/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/chrome_slices/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/chrome_slices/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/counter/controller.ts b/ui/src/tracks/counter/controller.ts
index 5b230f3..016a9e7 100644
--- a/ui/src/tracks/counter/controller.ts
+++ b/ui/src/tracks/counter/controller.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {NUM, NUM_NULL} from '../../common/query_iterator';
+import {NUM, NUM_NULL} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {
TrackController,
@@ -47,7 +47,7 @@
if (!this.setup) {
if (this.config.namespace === undefined) {
- await this.queryV2(`
+ await this.query(`
create view ${this.tableName('counter_view')} as
select
id,
@@ -59,7 +59,7 @@
where track_id = ${this.config.trackId};
`);
} else {
- await this.queryV2(`
+ await this.query(`
create view ${this.tableName('counter_view')} as
select
id,
@@ -72,7 +72,7 @@
`);
}
- const maxDurResult = await this.queryV2(`
+ const maxDurResult = await this.query(`
select
max(
iif(dur != -1, dur, (select end_ts from trace_bounds) - ts)
@@ -81,7 +81,7 @@
`);
this.maxDurNs = maxDurResult.firstRow({maxDur: NUM_NULL}).maxDur || 0;
- const queryRes = await this.queryV2(`
+ const queryRes = await this.query(`
select
ifnull(max(value), 0) as maxValue,
ifnull(min(value), 0) as minValue,
@@ -98,7 +98,7 @@
this.setup = true;
}
- const queryRes = await this.queryV2(`
+ const queryRes = await this.query(`
select
(ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
min(value) as minValue,
diff --git a/ui/src/tracks/counter/frontend.ts b/ui/src/tracks/counter/frontend.ts
index 186b1e1..2836c43 100644
--- a/ui/src/tracks/counter/frontend.ts
+++ b/ui/src/tracks/counter/frontend.ts
@@ -17,11 +17,10 @@
import {searchSegment} from '../../base/binary_search';
import {assertTrue} from '../../base/logging';
import {Actions} from '../../common/actions';
-import {TrackState} from '../../common/state';
import {toNs} from '../../common/time';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
-import {Track} from '../../frontend/track';
+import {NewTrackArgs, Track} from '../../frontend/track';
import {TrackButton, TrackButtonAttrs} from '../../frontend/track_panel';
import {trackRegistry} from '../../frontend/track_registry';
@@ -81,8 +80,8 @@
class CounterTrack extends Track<Config, Data> {
static readonly kind = COUNTER_TRACK_KIND;
- static create(trackState: TrackState): CounterTrack {
- return new CounterTrack(trackState);
+ static create(args: NewTrackArgs): CounterTrack {
+ return new CounterTrack(args);
}
private mouseXpos = 0;
@@ -90,8 +89,8 @@
private hoveredTs: number|undefined = undefined;
private hoveredTsEnd: number|undefined = undefined;
- constructor(trackState: TrackState) {
- super(trackState);
+ constructor(args: NewTrackArgs) {
+ super(args);
}
getHeight() {
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/counter/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/counter/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/counter/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/cpu_freq/controller.ts b/ui/src/tracks/cpu_freq/controller.ts
index c457da7..d5a29de 100644
--- a/ui/src/tracks/cpu_freq/controller.ts
+++ b/ui/src/tracks/cpu_freq/controller.ts
@@ -13,8 +13,7 @@
// limitations under the License.
import {assertTrue} from '../../base/logging';
-import {NUM, NUM_NULL} from '../../common/query_iterator';
-import {QueryResult} from '../../common/query_result';
+import {NUM, NUM_NULL, QueryResult} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {
TrackController,
@@ -41,7 +40,7 @@
this.maximumValueSeen = await this.queryMaxFrequency();
this.maxDurNs = await this.queryMaxSourceDur();
- const iter = (await this.queryV2(`
+ const iter = (await this.query(`
select max(ts) as maxTs, dur, count(1) as rowCount
from ${this.tableName('freq_idle')}
`)).firstRow({maxTs: NUM_NULL, dur: NUM_NULL, rowCount: NUM});
@@ -59,7 +58,7 @@
return;
}
- await this.queryV2(`
+ await this.query(`
create table ${this.tableName('freq_idle_cached')} as
select
(ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as cachedTsq,
@@ -130,7 +129,7 @@
const isCached = this.cachedBucketNs <= bucketNs;
if (isCached) {
- return this.queryV2(`
+ return this.query(`
select
cachedTsq / ${bucketNs} * ${bucketNs} as tsq,
min(minFreq) as minFreq,
@@ -145,14 +144,14 @@
order by tsq
`);
}
- const minTsFreq = await this.queryV2(`
+ const minTsFreq = await this.query(`
select ifnull(max(ts), 0) as minTs from ${this.tableName('freq')}
where ts < ${startNs}
`);
let minTs = minTsFreq.iter({minTs: NUM}).minTs;
if (this.config.idleTrackId !== undefined) {
- const minTsIdle = await this.queryV2(`
+ const minTsIdle = await this.query(`
select ifnull(max(ts), 0) as minTs from ${this.tableName('idle')}
where ts < ${startNs}
`);
@@ -162,7 +161,7 @@
const geqConstraint = this.config.idleTrackId === undefined ?
`ts >= ${minTs}` :
`source_geq(ts, ${minTs})`;
- return this.queryV2(`
+ return this.query(`
select
(ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
min(freqValue) as minFreq,
@@ -179,7 +178,7 @@
}
private async queryMaxFrequency(): Promise<number> {
- const result = await this.queryV2(`
+ const result = await this.query(`
select max(freqValue) as maxFreq
from ${this.tableName('freq')}
`);
@@ -187,20 +186,20 @@
}
private async queryMaxSourceDur(): Promise<number> {
- const maxDurFreqResult = await this.queryV2(
+ const maxDurFreqResult = await this.query(
`select ifnull(max(dur), 0) as maxDur from ${this.tableName('freq')}`);
const maxDurNs = maxDurFreqResult.firstRow({'maxDur': NUM}).maxDur;
if (this.config.idleTrackId === undefined) {
return maxDurNs;
}
- const maxDurIdleResult = await this.queryV2(
+ const maxDurIdleResult = await this.query(
`select ifnull(max(dur), 0) as maxDur from ${this.tableName('idle')}`);
return Math.max(maxDurNs, maxDurIdleResult.firstRow({maxDur: NUM}).maxDur);
}
private async createFreqIdleViews() {
- await this.queryV2(`create view ${this.tableName('freq')} as
+ await this.query(`create view ${this.tableName('freq')} as
select
ts,
dur,
@@ -210,7 +209,7 @@
`);
if (this.config.idleTrackId === undefined) {
- await this.queryV2(`create view ${this.tableName('freq_idle')} as
+ await this.query(`create view ${this.tableName('freq_idle')} as
select
ts,
dur,
@@ -221,7 +220,7 @@
return;
}
- await this.queryV2(`
+ await this.query(`
create view ${this.tableName('idle')} as
select
ts,
@@ -231,7 +230,7 @@
where track_id = ${this.config.idleTrackId};
`);
- await this.queryV2(`
+ await this.query(`
create virtual table ${this.tableName('freq_idle')}
using span_join(${this.tableName('freq')}, ${this.tableName('idle')});
`);
diff --git a/ui/src/tracks/cpu_freq/frontend.ts b/ui/src/tracks/cpu_freq/frontend.ts
index 4e5c9e4..6feed5f 100644
--- a/ui/src/tracks/cpu_freq/frontend.ts
+++ b/ui/src/tracks/cpu_freq/frontend.ts
@@ -15,10 +15,9 @@
import {searchSegment} 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 {globals} from '../../frontend/globals';
-import {Track} from '../../frontend/track';
+import {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {
@@ -33,8 +32,8 @@
class CpuFreqTrack extends Track<Config, Data> {
static readonly kind = CPU_FREQ_TRACK_KIND;
- static create(trackState: TrackState): CpuFreqTrack {
- return new CpuFreqTrack(trackState);
+ static create(args: NewTrackArgs): CpuFreqTrack {
+ return new CpuFreqTrack(args);
}
private mouseXpos = 0;
@@ -43,8 +42,8 @@
private hoveredTsEnd: number|undefined = undefined;
private hoveredIdle: number|undefined = undefined;
- constructor(trackState: TrackState) {
- super(trackState);
+ constructor(args: NewTrackArgs) {
+ super(args);
}
getHeight() {
@@ -83,7 +82,7 @@
// Draw the CPU frequency graph.
const hue = hueForCpu(this.config.cpu);
let saturation = 45;
- if (globals.frontendLocalState.hoveredUtid !== -1) {
+ if (globals.state.hoveredUtid !== -1) {
saturation = 0;
}
ctx.fillStyle = `hsl(${hue}, ${saturation}%, 70%)`;
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/cpu_freq/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/cpu_freq/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/cpu_freq/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/cpu_profile/controller.ts b/ui/src/tracks/cpu_profile/controller.ts
index a6c5456..4e68e5f 100644
--- a/ui/src/tracks/cpu_profile/controller.ts
+++ b/ui/src/tracks/cpu_profile/controller.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {NUM} from '../../common/query_iterator';
+import {NUM} from '../../common/query_result';
import {
TrackController,
trackControllerRegistry
@@ -36,7 +36,7 @@
where utid = ${this.config.utid}
order by ts`;
- const result = await this.queryV2(query);
+ const result = await this.query(query);
const numRows = result.numRows();
const data: Data = {
start,
diff --git a/ui/src/tracks/cpu_profile/frontend.ts b/ui/src/tracks/cpu_profile/frontend.ts
index f0cc6af..cbaabb1 100644
--- a/ui/src/tracks/cpu_profile/frontend.ts
+++ b/ui/src/tracks/cpu_profile/frontend.ts
@@ -17,15 +17,15 @@
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';
import {TimeScale} from '../../frontend/time_scale';
-import {Track} from '../../frontend/track';
+import {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {Config, CPU_PROFILE_TRACK_KIND, Data} from './common';
+const BAR_HEIGHT = 3;
const MARGIN_TOP = 4.5;
const RECT_HEIGHT = 30.5;
@@ -35,16 +35,16 @@
class CpuProfileTrack extends Track<Config, Data> {
static readonly kind = CPU_PROFILE_TRACK_KIND;
- static create(trackState: TrackState): CpuProfileTrack {
- return new CpuProfileTrack(trackState);
+ static create(args: NewTrackArgs): CpuProfileTrack {
+ return new CpuProfileTrack(args);
}
- private centerY = this.getHeight() / 2;
- private markerWidth = (this.getHeight() - MARGIN_TOP) / 2;
+ private centerY = this.getHeight() / 2 + BAR_HEIGHT;
+ private markerWidth = (this.getHeight() - MARGIN_TOP - BAR_HEIGHT) / 2;
private hoveredTs: number|undefined = undefined;
- constructor(trackState: TrackState) {
- super(trackState);
+ constructor(args: NewTrackArgs) {
+ super(args);
}
getHeight() {
@@ -74,6 +74,26 @@
strokeWidth,
data.callsiteId[i]);
}
+
+ let startX = data.tsStarts.length ? data.tsStarts[0] : -1;
+ let endX = data.tsStarts.length ? data.tsStarts[0] : -1;
+ let lastCallsiteId = data.callsiteId.length ? data.callsiteId[0] : -1;
+ for (let i = 0; i < data.tsStarts.length; i++) {
+ const centerX = data.tsStarts[i];
+ const callsiteId = data.callsiteId[i];
+ if (lastCallsiteId !== callsiteId) {
+ if (startX !== endX) {
+ const leftPx = timeScale.timeToPx(fromNs(startX)) - this.markerWidth;
+ const rightPx = timeScale.timeToPx(fromNs(endX)) + this.markerWidth;
+ const width = rightPx - leftPx;
+ ctx.fillStyle = colorForSample(lastCallsiteId, false);
+ ctx.fillRect(leftPx, MARGIN_TOP, width, BAR_HEIGHT);
+ }
+ startX = centerX;
+ }
+ endX = centerX;
+ lastCallsiteId = callsiteId;
+ }
}
drawMarker(
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/cpu_profile/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/cpu_profile/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/cpu_profile/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/cpu_slices/controller.ts b/ui/src/tracks/cpu_slices/controller.ts
index 2d891ef..9dc89bf 100644
--- a/ui/src/tracks/cpu_slices/controller.ts
+++ b/ui/src/tracks/cpu_slices/controller.ts
@@ -13,7 +13,7 @@
// limitations under the License.
import {assertTrue} from '../../base/logging';
-import {NUM} from '../../common/query_iterator';
+import {NUM} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {
TrackController,
@@ -29,7 +29,7 @@
private maxDurNs = 0;
async onSetup() {
- await this.queryV2(`
+ await this.query(`
create view ${this.tableName('sched')} as
select
ts,
@@ -40,7 +40,7 @@
where cpu = ${this.config.cpu} and utid != 0
`);
- const queryRes = await this.queryV2(`
+ const queryRes = await this.query(`
select ifnull(max(dur), 0) as maxDur, count(1) as rowCount
from ${this.tableName('sched')}
`);
@@ -51,7 +51,7 @@
if (bucketNs === undefined) {
return;
}
- await this.queryV2(`
+ await this.query(`
create table ${this.tableName('sched_cached')} as
select
(ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as cached_tsq,
@@ -90,7 +90,7 @@
isCached ? this.tableName('sched_cached') : this.tableName('sched');
const constraintColumn = isCached ? 'cached_tsq' : 'ts';
- const queryRes = await this.queryV2(`
+ const queryRes = await this.query(`
select
${queryTsq} as tsq,
ts,
@@ -127,8 +127,6 @@
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.utids[row] = it.utid;
@@ -139,8 +137,7 @@
}
async onDestroy() {
- await this.queryV2(
- `drop table if exists ${this.tableName('sched_cached')}`);
+ await this.query(`drop table if exists ${this.tableName('sched_cached')}`);
}
}
diff --git a/ui/src/tracks/cpu_slices/frontend.ts b/ui/src/tracks/cpu_slices/frontend.ts
index b6ca8d7..e81c55f 100644
--- a/ui/src/tracks/cpu_slices/frontend.ts
+++ b/ui/src/tracks/cpu_slices/frontend.ts
@@ -17,11 +17,10 @@
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 {globals} from '../../frontend/globals';
-import {Track} from '../../frontend/track';
+import {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {
@@ -36,15 +35,15 @@
class CpuSliceTrack extends Track<Config, Data> {
static readonly kind = CPU_SLICE_TRACK_KIND;
- static create(trackState: TrackState): CpuSliceTrack {
- return new CpuSliceTrack(trackState);
+ static create(args: NewTrackArgs): CpuSliceTrack {
+ return new CpuSliceTrack(args);
}
private mouseXpos?: number;
private utidHoveredInThisTrack = -1;
- constructor(trackState: TrackState) {
- super(trackState);
+ constructor(args: NewTrackArgs) {
+ super(args);
}
getHeight(): number {
@@ -99,9 +98,9 @@
const threadInfo = globals.threads.get(utid);
const pid = threadInfo && threadInfo.pid ? threadInfo.pid : -1;
- const isHovering = globals.frontendLocalState.hoveredUtid !== -1;
- const isThreadHovered = globals.frontendLocalState.hoveredUtid === utid;
- const isProcessHovered = globals.frontendLocalState.hoveredPid === pid;
+ const isHovering = globals.state.hoveredUtid !== -1;
+ const isThreadHovered = globals.state.hoveredUtid === utid;
+ const isProcessHovered = globals.state.hoveredPid === pid;
const color = colorForThread(threadInfo);
if (isHovering && !isThreadHovered) {
if (!isProcessHovered) {
@@ -230,7 +229,7 @@
const {timeScale} = globals.frontendLocalState;
if (y < MARGIN_TOP || y > MARGIN_TOP + RECT_HEIGHT) {
this.utidHoveredInThisTrack = -1;
- globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
+ globals.dispatch(Actions.setHoveredUtidAndPid({utid: -1, pid: -1}));
return;
}
const t = timeScale.pxToTime(x);
@@ -248,12 +247,13 @@
this.utidHoveredInThisTrack = hoveredUtid;
const threadInfo = globals.threads.get(hoveredUtid);
const hoveredPid = threadInfo ? (threadInfo.pid ? threadInfo.pid : -1) : -1;
- globals.frontendLocalState.setHoveredUtidAndPid(hoveredUtid, hoveredPid);
+ globals.dispatch(
+ Actions.setHoveredUtidAndPid({utid: hoveredUtid, pid: hoveredPid}));
}
onMouseOut() {
this.utidHoveredInThisTrack = -1;
- globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
+ globals.dispatch(Actions.setHoveredUtidAndPid({utid: -1, pid: -1}));
this.mouseXpos = 0;
}
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/cpu_slices/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/cpu_slices/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/cpu_slices/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/debug_slices/controller.ts b/ui/src/tracks/debug_slices/controller.ts
index 8400af8..0b761a3 100644
--- a/ui/src/tracks/debug_slices/controller.ts
+++ b/ui/src/tracks/debug_slices/controller.ts
@@ -13,7 +13,7 @@
// limitations under the License.
import {Actions} from '../../common/actions';
-import {NUM, NUM_NULL, STR} from '../../common/query_iterator';
+import {NUM, NUM_NULL, STR} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {globals} from '../../controller/globals';
import {
@@ -27,7 +27,7 @@
static readonly kind = DEBUG_SLICE_TRACK_KIND;
async onReload() {
- const rawResult = await this.queryV2(
+ const rawResult = await this.query(
`select ifnull(max(depth), 1) as maxDepth from debug_slices`);
const maxDepth = rawResult.firstRow({maxDepth: NUM}).maxDepth;
globals.dispatch(
@@ -36,7 +36,7 @@
async onBoundsChange(start: number, end: number, resolution: number):
Promise<Data> {
- const queryRes = await this.queryV2(`select
+ const queryRes = await this.query(`select
ifnull(id, -1) as id,
ifnull(name, '[null]') as name,
ts,
diff --git a/ui/src/tracks/debug_slices/frontend.ts b/ui/src/tracks/debug_slices/frontend.ts
index bdda433..5f20bee 100644
--- a/ui/src/tracks/debug_slices/frontend.ts
+++ b/ui/src/tracks/debug_slices/frontend.ts
@@ -15,9 +15,8 @@
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 {NewTrackArgs, Track} from '../../frontend/track';
import {TrackButton, TrackButtonAttrs} from '../../frontend/track_panel';
import {trackRegistry} from '../../frontend/track_registry';
import {ChromeSliceTrack} from '../chrome_slices/frontend';
@@ -26,8 +25,8 @@
export class DebugSliceTrack extends ChromeSliceTrack {
static readonly kind = DEBUG_SLICE_TRACK_KIND;
- static create(trackState: TrackState): Track {
- return new DebugSliceTrack(trackState);
+ static create(args: NewTrackArgs): Track {
+ return new DebugSliceTrack(args);
}
getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/debug_slices/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/debug_slices/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/debug_slices/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/expected_frames/controller.ts b/ui/src/tracks/expected_frames/controller.ts
index 5227a81..3265c98 100644
--- a/ui/src/tracks/expected_frames/controller.ts
+++ b/ui/src/tracks/expected_frames/controller.ts
@@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {assertTrue} from '../../base/logging';
-import {NUM, NUM_NULL, STR} from '../../common/query_iterator';
+import {NUM, NUM_NULL, STR} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {
TrackController,
@@ -38,7 +37,7 @@
const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
if (this.maxDurNs === 0) {
- const maxDurResult = await this.queryV2(`
+ const maxDurResult = await this.query(`
select max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
as maxDur
from experimental_slice_layout
@@ -47,7 +46,7 @@
this.maxDurNs = maxDurResult.firstRow({maxDur: NUM_NULL}).maxDur || 0;
}
- const queryRes = await this.queryV2(`
+ const queryRes = await this.query(`
SELECT
(ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
ts,
@@ -113,8 +112,6 @@
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] = it.layoutDepth;
diff --git a/ui/src/tracks/expected_frames/frontend.ts b/ui/src/tracks/expected_frames/frontend.ts
index 441f098..219a017 100644
--- a/ui/src/tracks/expected_frames/frontend.ts
+++ b/ui/src/tracks/expected_frames/frontend.ts
@@ -11,8 +11,7 @@
// 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 {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {ChromeSliceTrack} from '../chrome_slices/frontend';
@@ -20,8 +19,8 @@
export class ExpectedFramesSliceTrack extends ChromeSliceTrack {
static readonly kind = EXPECTED_FRAMES_SLICE_TRACK_KIND;
- static create(trackState: TrackState): Track {
- return new ExpectedFramesSliceTrack(trackState);
+ static create(args: NewTrackArgs): Track {
+ return new ExpectedFramesSliceTrack(args);
}
}
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/expected_frames/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/expected_frames/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/expected_frames/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/heap_profile/controller.ts b/ui/src/tracks/heap_profile/controller.ts
index 9873744..a79dc3d 100644
--- a/ui/src/tracks/heap_profile/controller.ts
+++ b/ui/src/tracks/heap_profile/controller.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {NUM, STR} from '../../common/query_iterator';
+import {NUM, STR} from '../../common/query_result';
import {
TrackController,
trackControllerRegistry
@@ -38,7 +38,7 @@
types: new Array<string>()
};
}
- const queryRes = await this.queryV2(`
+ const queryRes = await this.query(`
select * from
(select distinct(ts) as ts, 'native' as type from heap_profile_allocation
where upid = ${this.config.upid}
diff --git a/ui/src/tracks/heap_profile/frontend.ts b/ui/src/tracks/heap_profile/frontend.ts
index c9c7466..2b88f13 100644
--- a/ui/src/tracks/heap_profile/frontend.ts
+++ b/ui/src/tracks/heap_profile/frontend.ts
@@ -14,12 +14,11 @@
import {searchSegment} from '../../base/binary_search';
import {Actions} from '../../common/actions';
-import {TrackState} from '../../common/state';
import {fromNs, toNs} from '../../common/time';
-import {HEAP_PROFILE_HOVERED_COLOR} from '../../frontend/flamegraph';
+import {FLAMEGRAPH_HOVERED_COLOR} from '../../frontend/flamegraph';
import {globals} from '../../frontend/globals';
import {TimeScale} from '../../frontend/time_scale';
-import {Track} from '../../frontend/track';
+import {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {Config, Data, HEAP_PROFILE_TRACK_KIND} from './common';
@@ -32,16 +31,16 @@
class HeapProfileTrack extends Track<Config, Data> {
static readonly kind = HEAP_PROFILE_TRACK_KIND;
- static create(trackState: TrackState): HeapProfileTrack {
- return new HeapProfileTrack(trackState);
+ static create(args: NewTrackArgs): HeapProfileTrack {
+ return new HeapProfileTrack(args);
}
private centerY = this.getHeight() / 2;
private markerWidth = (this.getHeight() - MARGIN_TOP) / 2;
private hoveredTs: number|undefined = undefined;
- constructor(trackState: TrackState) {
- super(trackState);
+ constructor(args: NewTrackArgs) {
+ super(args);
}
getHeight() {
@@ -82,10 +81,10 @@
ctx.lineTo(x + this.markerWidth, y);
ctx.lineTo(x, y - this.markerWidth);
ctx.closePath();
- ctx.fillStyle = isHovered ? HEAP_PROFILE_HOVERED_COLOR : HEAP_PROFILE_COLOR;
+ ctx.fillStyle = isHovered ? FLAMEGRAPH_HOVERED_COLOR : HEAP_PROFILE_COLOR;
ctx.fill();
if (strokeWidth > 0) {
- ctx.strokeStyle = HEAP_PROFILE_HOVERED_COLOR;
+ ctx.strokeStyle = FLAMEGRAPH_HOVERED_COLOR;
ctx.lineWidth = strokeWidth;
ctx.stroke();
}
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/heap_profile/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/heap_profile/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/heap_profile/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/config/jest.individual.unit.config.js b/ui/src/tracks/perf_samples_profile/common.ts
similarity index 70%
copy from ui/config/jest.individual.unit.config.js
copy to ui/src/tracks/perf_samples_profile/common.ts
index 7d9d2f5..1169445 100644
--- a/ui/config/jest.individual.unit.config.js
+++ b/ui/src/tracks/perf_samples_profile/common.ts
@@ -11,12 +11,14 @@
// WITHOUT 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';
-const path = require('path');
+export const PERF_SAMPLES_PROFILE_TRACK_KIND = 'PerfSamplesProfileTrack';
-// 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'},
+export interface Data extends TrackData {
+ tsStartsNs: Float64Array;
+}
+
+export interface Config {
+ upid: number;
}
diff --git a/ui/src/tracks/perf_samples_profile/controller.ts b/ui/src/tracks/perf_samples_profile/controller.ts
new file mode 100644
index 0000000..5122d15
--- /dev/null
+++ b/ui/src/tracks/perf_samples_profile/controller.ts
@@ -0,0 +1,62 @@
+// 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 {NUM} from '../../common/query_result';
+import {
+ TrackController,
+ trackControllerRegistry
+} from '../../controller/track_controller';
+
+import {
+ Config,
+ Data,
+ PERF_SAMPLES_PROFILE_TRACK_KIND,
+} from './common';
+
+class PerfSamplesProfileTrackController extends TrackController<Config, Data> {
+ static readonly kind = PERF_SAMPLES_PROFILE_TRACK_KIND;
+ async onBoundsChange(start: number, end: number, resolution: number):
+ Promise<Data> {
+ if (this.config.upid === undefined) {
+ return {
+ start,
+ end,
+ resolution,
+ length: 0,
+ tsStartsNs: new Float64Array()
+ };
+ }
+ const queryRes = await this.query(`
+ select ts, upid from perf_sample
+ join thread using (utid)
+ where upid = ${this.config.upid}
+ order by ts`);
+ const numRows = queryRes.numRows();
+ const data: Data = {
+ start,
+ end,
+ resolution,
+ length: numRows,
+ tsStartsNs: new Float64Array(numRows)
+ };
+
+ const it = queryRes.iter({ts: NUM});
+ for (let row = 0; it.valid(); it.next(), row++) {
+ data.tsStartsNs[row] = it.ts;
+ }
+ return data;
+ }
+}
+
+trackControllerRegistry.register(PerfSamplesProfileTrackController);
diff --git a/ui/src/tracks/perf_samples_profile/frontend.ts b/ui/src/tracks/perf_samples_profile/frontend.ts
new file mode 100644
index 0000000..822e17d
--- /dev/null
+++ b/ui/src/tracks/perf_samples_profile/frontend.ts
@@ -0,0 +1,152 @@
+// 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 {searchSegment} from '../../base/binary_search';
+import {Actions} from '../../common/actions';
+import {fromNs, toNs} from '../../common/time';
+import {FLAMEGRAPH_HOVERED_COLOR} from '../../frontend/flamegraph';
+import {globals} from '../../frontend/globals';
+import {TimeScale} from '../../frontend/time_scale';
+import {NewTrackArgs, Track} from '../../frontend/track';
+import {trackRegistry} from '../../frontend/track_registry';
+
+import {Config, Data, PERF_SAMPLES_PROFILE_TRACK_KIND} from './common';
+
+const PERP_SAMPLE_COLOR = 'hsl(224, 45%, 70%)';
+
+// 0.5 Makes the horizontal lines sharp.
+const MARGIN_TOP = 4.5;
+const RECT_HEIGHT = 30.5;
+
+class PerfSamplesProfileTrack extends Track<Config, Data> {
+ static readonly kind = PERF_SAMPLES_PROFILE_TRACK_KIND;
+ static create(args: NewTrackArgs): PerfSamplesProfileTrack {
+ return new PerfSamplesProfileTrack(args);
+ }
+
+ private centerY = this.getHeight() / 2;
+ private markerWidth = (this.getHeight() - MARGIN_TOP) / 2;
+ private hoveredTs: number|undefined = undefined;
+
+ constructor(args: NewTrackArgs) {
+ super(args);
+ }
+
+ getHeight() {
+ return MARGIN_TOP + RECT_HEIGHT - 1;
+ }
+
+ renderCanvas(ctx: CanvasRenderingContext2D): void {
+ const {
+ timeScale,
+ } = globals.frontendLocalState;
+ const data = this.data();
+
+ if (data === undefined) return;
+
+ for (let i = 0; i < data.tsStartsNs.length; i++) {
+ const centerX = data.tsStartsNs[i];
+ const selection = globals.state.currentSelection;
+ const isHovered = this.hoveredTs === centerX;
+ const isSelected = selection !== null &&
+ selection.kind === 'PERF_SAMPLES' && selection.ts === centerX;
+ const strokeWidth = isSelected ? 3 : 0;
+ this.drawMarker(
+ ctx,
+ timeScale.timeToPx(fromNs(centerX)),
+ this.centerY,
+ isHovered,
+ strokeWidth);
+ }
+ }
+
+ drawMarker(
+ ctx: CanvasRenderingContext2D, x: number, y: number, isHovered: boolean,
+ strokeWidth: number): void {
+ ctx.beginPath();
+ ctx.moveTo(x, y - this.markerWidth);
+ ctx.lineTo(x - this.markerWidth, y);
+ ctx.lineTo(x, y + this.markerWidth);
+ ctx.lineTo(x + this.markerWidth, y);
+ ctx.lineTo(x, y - this.markerWidth);
+ ctx.closePath();
+ ctx.fillStyle = isHovered ? FLAMEGRAPH_HOVERED_COLOR : PERP_SAMPLE_COLOR;
+ ctx.fill();
+ if (strokeWidth > 0) {
+ ctx.strokeStyle = FLAMEGRAPH_HOVERED_COLOR;
+ ctx.lineWidth = strokeWidth;
+ ctx.stroke();
+ }
+ }
+
+ onMouseMove({x, y}: {x: number, y: number}) {
+ const data = this.data();
+ if (data === undefined) return;
+ const {timeScale} = globals.frontendLocalState;
+ const time = toNs(timeScale.pxToTime(x));
+ const [left, right] = searchSegment(data.tsStartsNs, time);
+ const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
+ this.hoveredTs = index === -1 ? undefined : data.tsStartsNs[index];
+ }
+
+ onMouseOut() {
+ this.hoveredTs = undefined;
+ }
+
+ onMouseClick({x, y}: {x: number, y: number}) {
+ const data = this.data();
+ if (data === undefined) return false;
+ const {timeScale} = globals.frontendLocalState;
+
+ const time = toNs(timeScale.pxToTime(x));
+ const [left, right] = searchSegment(data.tsStartsNs, time);
+
+ const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
+
+ if (index !== -1) {
+ const ts = data.tsStartsNs[index];
+ globals.makeSelection(Actions.selectPerfSamples(
+ {id: index, upid: this.config.upid, ts, type: 'perf'}));
+ return true;
+ }
+ return false;
+ }
+
+ // If the markers overlap the rightmost one will be selected.
+ findTimestampIndex(
+ left: number, timeScale: TimeScale, data: Data, x: number, y: number,
+ right: number): number {
+ let index = -1;
+ if (left !== -1) {
+ const centerX = timeScale.timeToPx(fromNs(data.tsStartsNs[left]));
+ if (this.isInMarker(x, y, centerX)) {
+ index = left;
+ }
+ }
+ if (right !== -1) {
+ const centerX = timeScale.timeToPx(fromNs(data.tsStartsNs[right]));
+ if (this.isInMarker(x, y, centerX)) {
+ index = right;
+ }
+ }
+ return index;
+ }
+
+ isInMarker(x: number, y: number, centerX: number) {
+ return Math.abs(x - centerX) + Math.abs(y - this.centerY) <=
+ this.markerWidth;
+ }
+}
+
+trackRegistry.register(PerfSamplesProfileTrack);
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/perf_samples_profile/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/perf_samples_profile/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/perf_samples_profile/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/process_scheduling/controller.ts b/ui/src/tracks/process_scheduling/controller.ts
index 9441448..13ecee9 100644
--- a/ui/src/tracks/process_scheduling/controller.ts
+++ b/ui/src/tracks/process_scheduling/controller.ts
@@ -13,8 +13,7 @@
// limitations under the License.
import {assertTrue} from '../../base/logging';
-import {NUM} from '../../common/query_iterator';
-import {QueryResult} from '../../common/query_result';
+import {NUM, QueryResult} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {
TrackController,
@@ -45,7 +44,7 @@
assertTrue(cpus.length > 0);
this.maxCpu = Math.max(...cpus) + 1;
- const result = (await this.queryV2(`
+ const result = (await this.query(`
select ifnull(max(dur), 0) as maxDur, count(1) as count
from ${this.tableName('process_sched')}
`)).iter({maxDur: NUM, count: NUM});
@@ -57,7 +56,7 @@
if (bucketNs === undefined) {
return;
}
- await this.queryV2(`
+ await this.query(`
create table ${this.tableName('process_sched_cached')} as
select
(ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as cached_tsq,
@@ -121,8 +120,6 @@
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.cpus[row] = it.cpu;
@@ -140,7 +137,7 @@
const queryTable = isCached ? this.tableName('process_sched_cached') :
this.tableName('process_sched');
const constraintColumn = isCached ? 'cached_tsq' : 'ts';
- return this.queryV2(`
+ return this.query(`
select
${tsq} as tsq,
ts,
@@ -157,7 +154,7 @@
}
private async createSchedView() {
- await this.queryV2(`
+ await this.query(`
create view ${this.tableName('process_sched')} as
select ts, dur, cpu, utid
from experimental_sched_upid
diff --git a/ui/src/tracks/process_scheduling/frontend.ts b/ui/src/tracks/process_scheduling/frontend.ts
index e7c4eb1..dc5f9c6 100644
--- a/ui/src/tracks/process_scheduling/frontend.ts
+++ b/ui/src/tracks/process_scheduling/frontend.ts
@@ -14,11 +14,11 @@
import {searchEq, searchRange, searchSegment} from '../../base/binary_search';
import {assertTrue} from '../../base/logging';
+import {Actions} from '../../common/actions';
import {colorForThread} from '../../common/colorizer';
-import {TrackState} from '../../common/state';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
-import {Track} from '../../frontend/track';
+import {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {
@@ -33,15 +33,15 @@
class ProcessSchedulingTrack extends Track<Config, Data> {
static readonly kind = PROCESS_SCHEDULING_TRACK_KIND;
- static create(trackState: TrackState): ProcessSchedulingTrack {
- return new ProcessSchedulingTrack(trackState);
+ static create(args: NewTrackArgs): ProcessSchedulingTrack {
+ return new ProcessSchedulingTrack(args);
}
private mouseXpos?: number;
private utidHoveredInThisTrack = -1;
- constructor(trackState: TrackState) {
- super(trackState);
+ constructor(args: NewTrackArgs) {
+ super(args);
}
getHeight(): number {
@@ -91,9 +91,9 @@
const threadInfo = globals.threads.get(utid);
const pid = (threadInfo ? threadInfo.pid : -1) || -1;
- const isHovering = globals.frontendLocalState.hoveredUtid !== -1;
- const isThreadHovered = globals.frontendLocalState.hoveredUtid === utid;
- const isProcessHovered = globals.frontendLocalState.hoveredPid === pid;
+ const isHovering = globals.state.hoveredUtid !== -1;
+ const isThreadHovered = globals.state.hoveredUtid === utid;
+ const isProcessHovered = globals.state.hoveredPid === pid;
const color = colorForThread(threadInfo);
if (isHovering && !isThreadHovered) {
if (!isProcessHovered) {
@@ -124,14 +124,13 @@
}
}
-
onMouseMove({x, y}: {x: number, y: number}) {
const data = this.data();
this.mouseXpos = x;
if (data === undefined) return;
if (y < MARGIN_TOP || y > MARGIN_TOP + RECT_HEIGHT) {
this.utidHoveredInThisTrack = -1;
- globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
+ globals.dispatch(Actions.setHoveredUtidAndPid({utid: -1, pid: -1}));
return;
}
@@ -143,7 +142,7 @@
const [i, j] = searchRange(data.starts, t, searchEq(data.cpus, cpu));
if (i === j || i >= data.starts.length || t > data.ends[i]) {
this.utidHoveredInThisTrack = -1;
- globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
+ globals.dispatch(Actions.setHoveredUtidAndPid({utid: -1, pid: -1}));
return;
}
@@ -151,12 +150,12 @@
this.utidHoveredInThisTrack = utid;
const threadInfo = globals.threads.get(utid);
const pid = threadInfo ? (threadInfo.pid ? threadInfo.pid : -1) : -1;
- globals.frontendLocalState.setHoveredUtidAndPid(utid, pid);
+ globals.dispatch(Actions.setHoveredUtidAndPid({utid, pid}));
}
onMouseOut() {
this.utidHoveredInThisTrack = -1;
- globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
+ globals.dispatch(Actions.setHoveredUtidAndPid({utid: -1, pid: -1}));
this.mouseXpos = 0;
}
}
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/process_scheduling/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/process_scheduling/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/process_scheduling/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/process_summary/controller.ts b/ui/src/tracks/process_summary/controller.ts
index 9e6ec5e..8241562 100644
--- a/ui/src/tracks/process_summary/controller.ts
+++ b/ui/src/tracks/process_summary/controller.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {NUM} from '../../common/query_iterator';
+import {NUM} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {LIMIT} from '../../common/track_data';
import {
@@ -39,12 +39,12 @@
const endNs = toNs(end);
if (this.setup === false) {
- await this.queryV2(
+ await this.query(
`create virtual table ${this.tableName('window')} using window;`);
let utids = [this.config.utid];
if (this.config.upid) {
- const threadQuery = await this.queryV2(
+ const threadQuery = await this.query(
`select utid from thread where upid=${this.config.upid}`);
utids = [];
for (const it = threadQuery.iter({utid: NUM}); it.valid(); it.next()) {
@@ -52,7 +52,7 @@
}
}
- const trackQuery = await this.queryV2(
+ const trackQuery = await this.query(
`select id from thread_track where utid in (${utids.join(',')})`);
const tracks = [];
for (const it = trackQuery.iter({id: NUM}); it.valid(); it.next()) {
@@ -60,14 +60,14 @@
}
const processSliceView = this.tableName('process_slice_view');
- await this.queryV2(
+ await this.query(
`create view ${processSliceView} as ` +
// 0 as cpu is a dummy column to perform span join on.
`select ts, dur/${utids.length} as dur ` +
`from slice s ` +
`where depth = 0 and track_id in ` +
`(${tracks.join(',')})`);
- await this.queryV2(`create virtual table ${this.tableName('span')}
+ await this.query(`create virtual table ${this.tableName('span')}
using span_join(${processSliceView},
${this.tableName('window')});`);
this.setup = true;
@@ -79,7 +79,7 @@
const windowStartNs = Math.floor(startNs / bucketSizeNs) * bucketSizeNs;
const windowDurNs = Math.max(1, endNs - windowStartNs);
- await this.queryV2(`update ${this.tableName('window')} set
+ await this.query(`update ${this.tableName('window')} set
window_start=${windowStartNs},
window_dur=${windowDurNs},
quantum=${bucketSizeNs}
@@ -113,7 +113,7 @@
utilizations: new Float64Array(numBuckets),
};
- const queryRes = await this.queryV2(query);
+ const queryRes = await this.query(query);
const it = queryRes.iter({bucket: NUM, utilization: NUM});
for (; it.valid(); it.next()) {
const bucket = it.bucket;
@@ -128,8 +128,8 @@
onDestroy(): void {
if (this.setup) {
- this.queryV2(`drop table ${this.tableName('window')}`);
- this.queryV2(`drop table ${this.tableName('span')}`);
+ this.query(`drop table ${this.tableName('window')}`);
+ this.query(`drop table ${this.tableName('span')}`);
this.setup = false;
}
}
diff --git a/ui/src/tracks/process_summary/frontend.ts b/ui/src/tracks/process_summary/frontend.ts
index 0a259ca..b6d10f5 100644
--- a/ui/src/tracks/process_summary/frontend.ts
+++ b/ui/src/tracks/process_summary/frontend.ts
@@ -13,10 +13,9 @@
// limitations under the License.
import {colorForTid} from '../../common/colorizer';
-import {TrackState} from '../../common/state';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
-import {Track} from '../../frontend/track';
+import {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {
@@ -32,12 +31,12 @@
class ProcessSummaryTrack extends Track<Config, Data> {
static readonly kind = PROCESS_SUMMARY_TRACK;
- static create(trackState: TrackState): ProcessSummaryTrack {
- return new ProcessSummaryTrack(trackState);
+ static create(args: NewTrackArgs): ProcessSummaryTrack {
+ return new ProcessSummaryTrack(args);
}
- constructor(trackState: TrackState) {
- super(trackState);
+ constructor(args: NewTrackArgs) {
+ super(args);
}
getHeight(): number {
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/process_summary/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/process_summary/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/process_summary/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/src/tracks/thread_state/controller.ts b/ui/src/tracks/thread_state/controller.ts
index 0de3a3e..ca8355f 100644
--- a/ui/src/tracks/thread_state/controller.ts
+++ b/ui/src/tracks/thread_state/controller.ts
@@ -13,11 +13,7 @@
// limitations under the License.
import {assertFalse} from '../../base/logging';
-import {
- NUM,
- NUM_NULL,
- STR_NULL
-} from '../../common/query_iterator';
+import {NUM, NUM_NULL, STR_NULL} from '../../common/query_result';
import {translateState} from '../../common/thread_state';
import {fromNs, toNs} from '../../common/time';
import {
@@ -37,7 +33,7 @@
private maxDurNs = 0;
async onSetup() {
- await this.queryV2(`
+ await this.query(`
create view ${this.tableName('thread_state')} as
select
id,
@@ -45,12 +41,12 @@
dur,
cpu,
state,
- io_wait
+ io_wait as ioWait
from thread_state
where utid = ${this.config.utid} and utid != 0
`);
- const queryRes = await this.queryV2(`
+ const queryRes = await this.query(`
select ifnull(max(dur), 0) as maxDur
from ${this.tableName('thread_state')}
`);
@@ -75,17 +71,17 @@
max(dur) as dur,
ifnull(cast(cpu as integer), -1) as cpu,
state,
- io_wait,
+ ioWait,
ifnull(id, -1) as 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
+ group by tsq
+ order by tsq
`;
- const queryRes = await this.queryV2(query);
+ const queryRes = await this.query(query);
const numRows = queryRes.numRows();
const data: Data = {
@@ -102,7 +98,7 @@
};
const stringIndexes =
- new Map<{shortState: string, ioWait: boolean | undefined}, number>();
+ new Map<{shortState: string; ioWait: boolean | undefined}, number>();
function internState(shortState: string, ioWait: boolean|undefined) {
let idx = stringIndexes.get({shortState, ioWait});
if (idx !== undefined) return idx;
@@ -117,7 +113,7 @@
'dur': NUM,
'cpu': NUM,
'state': STR_NULL,
- 'io_wait': NUM_NULL,
+ 'ioWait': NUM_NULL,
'id': NUM,
});
for (let row = 0; it.valid(); it.next(), row++) {
@@ -131,7 +127,7 @@
const cpu = it.cpu;
const state = it.state || '[null]';
- const ioWait = it.io_wait === null ? undefined : !!it.io_wait;
+ const ioWait = it.ioWait === null ? undefined : !!it.ioWait;
const id = it.id;
// We should never have the end timestamp being the same as the bucket
@@ -148,8 +144,7 @@
}
async onDestroy() {
- await this.queryV2(
- `drop table if exists ${this.tableName('thread_state')}`);
+ await this.query(`drop table if exists ${this.tableName('thread_state')}`);
}
}
diff --git a/ui/src/tracks/thread_state/frontend.ts b/ui/src/tracks/thread_state/frontend.ts
index 0383010..62cd005 100644
--- a/ui/src/tracks/thread_state/frontend.ts
+++ b/ui/src/tracks/thread_state/frontend.ts
@@ -16,10 +16,9 @@
import {Actions} from '../../common/actions';
import {cropText} from '../../common/canvas_utils';
import {colorForState} from '../../common/colorizer';
-import {TrackState} from '../../common/state';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
-import {Track} from '../../frontend/track';
+import {NewTrackArgs, Track} from '../../frontend/track';
import {trackRegistry} from '../../frontend/track_registry';
import {
@@ -34,12 +33,12 @@
class ThreadStateTrack extends Track<Config, Data> {
static readonly kind = THREAD_STATE_TRACK_KIND;
- static create(trackState: TrackState): ThreadStateTrack {
- return new ThreadStateTrack(trackState);
+ static create(args: NewTrackArgs): ThreadStateTrack {
+ return new ThreadStateTrack(args);
}
- constructor(trackState: TrackState) {
- super(trackState);
+ constructor(args: NewTrackArgs) {
+ super(args);
}
getHeight(): number {
diff --git a/ui/config/headless_setup.js b/ui/src/tracks/thread_state/index.ts
similarity index 84%
copy from ui/config/headless_setup.js
copy to ui/src/tracks/thread_state/index.ts
index 7f8f93c..308406e 100644
--- a/ui/config/headless_setup.js
+++ b/ui/src/tracks/thread_state/index.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// 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.
@@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-module.exports = async function() {
-}
-
+import './controller';
+import './frontend';
diff --git a/ui/tsconfig.base.json b/ui/tsconfig.base.json
index 075b1b3..cd52245 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.
+ "inlineSources": true, // Adds source code to the '.map' file.
"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'.