Merge "Use M_PURGE_ALL instead M_PURGE."
diff --git a/Android.bp b/Android.bp
index e3a94e7..5a3186d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -593,6 +593,7 @@
":perfetto_src_tracing_common",
":perfetto_src_tracing_core_core",
":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_core_zlib_compressor",
":perfetto_src_tracing_ipc_common",
":perfetto_src_tracing_ipc_default_socket",
":perfetto_src_tracing_ipc_producer_producer",
@@ -660,10 +661,19 @@
defaults: [
"perfetto_defaults",
],
+ cflags: [
+ "-DZLIB_IMPLEMENTATION",
+ ],
target: {
android: {
shared_libs: [
"liblog",
+ "libz",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libz",
],
},
},
@@ -679,6 +689,7 @@
"src/android_internal/health_hal.cc",
"src/android_internal/incident_service.cc",
"src/android_internal/power_stats.cc",
+ "src/android_internal/statsd.cc",
"src/android_internal/statsd_logging.cc",
"src/android_internal/tracing_service_proxy.cc",
],
@@ -696,6 +707,7 @@
"libincident",
"liblog",
"libservices",
+ "libstatspull",
"libstatssocket",
"libtracingproxy",
"libutils",
@@ -2052,11 +2064,13 @@
":perfetto_src_trace_processor_metatrace",
":perfetto_src_trace_processor_metrics_metrics",
":perfetto_src_trace_processor_prelude_functions_functions",
+ ":perfetto_src_trace_processor_prelude_functions_interface",
":perfetto_src_trace_processor_prelude_operators_operators",
+ ":perfetto_src_trace_processor_prelude_table_functions_interface",
":perfetto_src_trace_processor_prelude_table_functions_table_functions",
":perfetto_src_trace_processor_sorter_sorter",
+ ":perfetto_src_trace_processor_sqlite_query_constraints",
":perfetto_src_trace_processor_sqlite_sqlite",
- ":perfetto_src_trace_processor_sqlite_sqlite_minimal",
":perfetto_src_trace_processor_storage_minimal",
":perfetto_src_trace_processor_storage_storage",
":perfetto_src_trace_processor_tables_tables",
@@ -9383,9 +9397,12 @@
name: "perfetto_src_trace_processor_db_db",
srcs: [
"src/trace_processor/db/column.cc",
+ "src/trace_processor/db/column_overlay.cc",
"src/trace_processor/db/column_storage.cc",
+ "src/trace_processor/db/null_overlay.cc",
"src/trace_processor/db/numeric_storage.cc",
"src/trace_processor/db/storage.cc",
+ "src/trace_processor/db/storage_overlay.cc",
"src/trace_processor/db/table.cc",
"src/trace_processor/db/view.cc",
],
@@ -10023,6 +10040,7 @@
"src/trace_processor/metrics/sql/android/java_heap_histogram.sql",
"src/trace_processor/metrics/sql/android/java_heap_stats.sql",
"src/trace_processor/metrics/sql/android/mem_stats_priority_breakdown.sql",
+ "src/trace_processor/metrics/sql/android/network_activity_template.sql",
"src/trace_processor/metrics/sql/android/p_state.sql",
"src/trace_processor/metrics/sql/android/power_drain_in_watts.sql",
"src/trace_processor/metrics/sql/android/power_profile_data.sql",
@@ -10152,13 +10170,20 @@
"src/trace_processor/prelude/functions/import.cc",
"src/trace_processor/prelude/functions/layout_functions.cc",
"src/trace_processor/prelude/functions/pprof_functions.cc",
- "src/trace_processor/prelude/functions/register_function.cc",
"src/trace_processor/prelude/functions/sqlite3_str_split.cc",
"src/trace_processor/prelude/functions/stack_functions.cc",
"src/trace_processor/prelude/functions/to_ftrace.cc",
],
}
+// GN: //src/trace_processor/prelude/functions:interface
+filegroup {
+ name: "perfetto_src_trace_processor_prelude_functions_interface",
+ srcs: [
+ "src/trace_processor/prelude/functions/sql_function.cc",
+ ],
+}
+
// GN: //src/trace_processor/prelude/functions:unittests
filegroup {
name: "perfetto_src_trace_processor_prelude_functions_unittests",
@@ -10184,6 +10209,14 @@
],
}
+// GN: //src/trace_processor/prelude/table_functions:interface
+filegroup {
+ name: "perfetto_src_trace_processor_prelude_table_functions_interface",
+ srcs: [
+ "src/trace_processor/prelude/table_functions/table_function.cc",
+ ],
+}
+
// GN: //src/trace_processor/prelude/table_functions:table_functions
filegroup {
name: "perfetto_src_trace_processor_prelude_table_functions_table_functions",
@@ -10198,7 +10231,6 @@
"src/trace_processor/prelude/table_functions/experimental_sched_upid.cc",
"src/trace_processor/prelude/table_functions/experimental_slice_layout.cc",
"src/trace_processor/prelude/table_functions/flamegraph_construction_algorithms.cc",
- "src/trace_processor/prelude/table_functions/table_function.cc",
"src/trace_processor/prelude/table_functions/view.cc",
],
}
@@ -10312,6 +10344,14 @@
],
}
+// GN: //src/trace_processor/sqlite:query_constraints
+filegroup {
+ name: "perfetto_src_trace_processor_sqlite_query_constraints",
+ srcs: [
+ "src/trace_processor/sqlite/query_constraints.cc",
+ ],
+}
+
// GN: //src/trace_processor/sqlite:sqlite
filegroup {
name: "perfetto_src_trace_processor_sqlite_sqlite",
@@ -10319,20 +10359,12 @@
"src/trace_processor/sqlite/db_sqlite_table.cc",
"src/trace_processor/sqlite/sql_stats_table.cc",
"src/trace_processor/sqlite/sqlite_engine.cc",
+ "src/trace_processor/sqlite/sqlite_table.cc",
"src/trace_processor/sqlite/sqlite_utils.cc",
"src/trace_processor/sqlite/stats_table.cc",
],
}
-// GN: //src/trace_processor/sqlite:sqlite_minimal
-filegroup {
- name: "perfetto_src_trace_processor_sqlite_sqlite_minimal",
- srcs: [
- "src/trace_processor/sqlite/query_constraints.cc",
- "src/trace_processor/sqlite/sqlite_table.cc",
- ],
-}
-
// GN: //src/trace_processor/sqlite:unittests
filegroup {
name: "perfetto_src_trace_processor_sqlite_unittests",
@@ -10348,14 +10380,18 @@
name: "perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
srcs: [
"src/trace_processor/stdlib/android/battery.sql",
+ "src/trace_processor/stdlib/android/battery_stats.sql",
"src/trace_processor/stdlib/android/binder.sql",
"src/trace_processor/stdlib/android/monitor_contention.sql",
+ "src/trace_processor/stdlib/android/network_packets.sql",
"src/trace_processor/stdlib/android/process_metadata.sql",
"src/trace_processor/stdlib/android/slices.sql",
"src/trace_processor/stdlib/android/startup/internal_startups_maxsdk28.sql",
"src/trace_processor/stdlib/android/startup/internal_startups_minsdk29.sql",
"src/trace_processor/stdlib/android/startup/internal_startups_minsdk33.sql",
"src/trace_processor/stdlib/android/startup/startups.sql",
+ "src/trace_processor/stdlib/android/statsd.sql",
+ "src/trace_processor/stdlib/chrome/chrome_scrolls.sql",
"src/trace_processor/stdlib/chrome/cpu_powerups.sql",
"src/trace_processor/stdlib/common/counters.sql",
"src/trace_processor/stdlib/common/cpus.sql",
@@ -11299,6 +11335,15 @@
"src/tracing/core/trace_packet_unittest.cc",
"src/tracing/core/trace_writer_impl_unittest.cc",
"src/tracing/core/tracing_service_impl_unittest.cc",
+ "src/tracing/core/zlib_compressor_unittest.cc",
+ ],
+}
+
+// GN: //src/tracing/core:zlib_compressor
+filegroup {
+ name: "perfetto_src_tracing_core_zlib_compressor",
+ srcs: [
+ "src/tracing/core/zlib_compressor.cc",
],
}
@@ -12027,17 +12072,19 @@
":perfetto_src_trace_processor_metrics_metrics",
":perfetto_src_trace_processor_metrics_unittests",
":perfetto_src_trace_processor_prelude_functions_functions",
+ ":perfetto_src_trace_processor_prelude_functions_interface",
":perfetto_src_trace_processor_prelude_functions_unittests",
":perfetto_src_trace_processor_prelude_operators_operators",
":perfetto_src_trace_processor_prelude_operators_unittests",
+ ":perfetto_src_trace_processor_prelude_table_functions_interface",
":perfetto_src_trace_processor_prelude_table_functions_table_functions",
":perfetto_src_trace_processor_prelude_table_functions_unittests",
":perfetto_src_trace_processor_rpc_rpc",
":perfetto_src_trace_processor_rpc_unittests",
":perfetto_src_trace_processor_sorter_sorter",
":perfetto_src_trace_processor_sorter_unittests",
+ ":perfetto_src_trace_processor_sqlite_query_constraints",
":perfetto_src_trace_processor_sqlite_sqlite",
- ":perfetto_src_trace_processor_sqlite_sqlite_minimal",
":perfetto_src_trace_processor_sqlite_unittests",
":perfetto_src_trace_processor_storage_minimal",
":perfetto_src_trace_processor_storage_storage",
@@ -12115,6 +12162,7 @@
":perfetto_src_tracing_core_service",
":perfetto_src_tracing_core_test_support",
":perfetto_src_tracing_core_unittests",
+ ":perfetto_src_tracing_core_zlib_compressor",
":perfetto_src_tracing_ipc_common",
":perfetto_src_tracing_ipc_consumer_consumer",
":perfetto_src_tracing_ipc_default_socket",
@@ -12711,13 +12759,15 @@
":perfetto_src_trace_processor_metatrace",
":perfetto_src_trace_processor_metrics_metrics",
":perfetto_src_trace_processor_prelude_functions_functions",
+ ":perfetto_src_trace_processor_prelude_functions_interface",
":perfetto_src_trace_processor_prelude_operators_operators",
+ ":perfetto_src_trace_processor_prelude_table_functions_interface",
":perfetto_src_trace_processor_prelude_table_functions_table_functions",
":perfetto_src_trace_processor_rpc_httpd",
":perfetto_src_trace_processor_rpc_rpc",
":perfetto_src_trace_processor_sorter_sorter",
+ ":perfetto_src_trace_processor_sqlite_query_constraints",
":perfetto_src_trace_processor_sqlite_sqlite",
- ":perfetto_src_trace_processor_sqlite_sqlite_minimal",
":perfetto_src_trace_processor_storage_minimal",
":perfetto_src_trace_processor_storage_storage",
":perfetto_src_trace_processor_tables_tables",
@@ -12934,11 +12984,13 @@
":perfetto_src_trace_processor_metatrace",
":perfetto_src_trace_processor_metrics_metrics",
":perfetto_src_trace_processor_prelude_functions_functions",
+ ":perfetto_src_trace_processor_prelude_functions_interface",
":perfetto_src_trace_processor_prelude_operators_operators",
+ ":perfetto_src_trace_processor_prelude_table_functions_interface",
":perfetto_src_trace_processor_prelude_table_functions_table_functions",
":perfetto_src_trace_processor_sorter_sorter",
+ ":perfetto_src_trace_processor_sqlite_query_constraints",
":perfetto_src_trace_processor_sqlite_sqlite",
- ":perfetto_src_trace_processor_sqlite_sqlite_minimal",
":perfetto_src_trace_processor_storage_minimal",
":perfetto_src_trace_processor_storage_storage",
":perfetto_src_trace_processor_tables_tables",
@@ -13043,15 +13095,22 @@
"src/traced/service/main.cc",
],
shared_libs: [
- "liblog",
"libperfetto",
],
+ host_supported: true,
init_rc: [
"perfetto.rc",
],
defaults: [
"perfetto_defaults",
],
+ target: {
+ android: {
+ shared_libs: [
+ "liblog",
+ ],
+ },
+ },
}
// GN: //src/profiling/perf:traced_perf
diff --git a/BUILD b/BUILD
index a8826c5..195292f 100644
--- a/BUILD
+++ b/BUILD
@@ -64,6 +64,152 @@
linkstatic = True,
)
+# GN target: //src/cloud_trace_processor:cloud_trace_processor
+perfetto_cc_library(
+ name = "cloud_trace_processor",
+ srcs = [
+ ":src_base_threading_threading",
+ ":src_cloud_trace_processor_sources",
+ ":src_kernel_utils_syscall_table",
+ ":src_protozero_proto_ring_buffer",
+ ":src_trace_processor_db_db",
+ ":src_trace_processor_export_json",
+ ":src_trace_processor_importers_android_bugreport_android_bugreport",
+ ":src_trace_processor_importers_common_common",
+ ":src_trace_processor_importers_common_parser_types",
+ ":src_trace_processor_importers_common_trace_parser_hdr",
+ ":src_trace_processor_importers_ftrace_ftrace_descriptors",
+ ":src_trace_processor_importers_ftrace_full",
+ ":src_trace_processor_importers_ftrace_minimal",
+ ":src_trace_processor_importers_fuchsia_fuchsia_record",
+ ":src_trace_processor_importers_fuchsia_full",
+ ":src_trace_processor_importers_fuchsia_minimal",
+ ":src_trace_processor_importers_gzip_full",
+ ":src_trace_processor_importers_i2c_full",
+ ":src_trace_processor_importers_json_full",
+ ":src_trace_processor_importers_json_minimal",
+ ":src_trace_processor_importers_memory_tracker_graph_processor",
+ ":src_trace_processor_importers_ninja_ninja",
+ ":src_trace_processor_importers_proto_full",
+ ":src_trace_processor_importers_proto_minimal",
+ ":src_trace_processor_importers_proto_packet_sequence_state_generation_hdr",
+ ":src_trace_processor_importers_proto_proto_importer_module",
+ ":src_trace_processor_importers_syscalls_full",
+ ":src_trace_processor_importers_systrace_full",
+ ":src_trace_processor_importers_systrace_systrace_line",
+ ":src_trace_processor_importers_systrace_systrace_parser",
+ ":src_trace_processor_lib",
+ ":src_trace_processor_metatrace",
+ ":src_trace_processor_metrics_metrics",
+ ":src_trace_processor_prelude_functions_functions",
+ ":src_trace_processor_prelude_functions_interface",
+ ":src_trace_processor_prelude_operators_operators",
+ ":src_trace_processor_prelude_table_functions_interface",
+ ":src_trace_processor_prelude_table_functions_table_functions",
+ ":src_trace_processor_prelude_table_functions_tables",
+ ":src_trace_processor_rpc_rpc",
+ ":src_trace_processor_sorter_sorter",
+ ":src_trace_processor_sqlite_query_constraints",
+ ":src_trace_processor_sqlite_sqlite",
+ ":src_trace_processor_storage_minimal",
+ ":src_trace_processor_storage_storage",
+ ":src_trace_processor_tables_tables",
+ ":src_trace_processor_tables_tables_python",
+ ":src_trace_processor_types_types",
+ ":src_trace_processor_util_bump_allocator",
+ ":src_trace_processor_util_descriptors",
+ ":src_trace_processor_util_glob",
+ ":src_trace_processor_util_gzip",
+ ":src_trace_processor_util_interned_message_view",
+ ":src_trace_processor_util_profile_builder",
+ ":src_trace_processor_util_proto_profiler",
+ ":src_trace_processor_util_proto_to_args_parser",
+ ":src_trace_processor_util_protozero_to_text",
+ ":src_trace_processor_util_sql_argument",
+ ":src_trace_processor_util_stack_traces_util",
+ ":src_trace_processor_util_stdlib",
+ ":src_trace_processor_util_util",
+ ":src_trace_processor_util_zip_reader",
+ ":src_trace_processor_views_views",
+ ],
+ hdrs = [
+ ":include_perfetto_base_base",
+ ":include_perfetto_ext_base_base",
+ ":include_perfetto_ext_base_threading_threading",
+ ":include_perfetto_ext_cloud_trace_processor_cloud_trace_processor",
+ ":include_perfetto_ext_trace_processor_demangle",
+ ":include_perfetto_ext_trace_processor_export_json",
+ ":include_perfetto_ext_trace_processor_importers_memory_tracker_memory_tracker",
+ ":include_perfetto_ext_traced_sys_stats_counters",
+ ":include_perfetto_protozero_protozero",
+ ":include_perfetto_public_abi_base",
+ ":include_perfetto_public_base",
+ ":include_perfetto_public_protozero",
+ ":include_perfetto_trace_processor_basic_types",
+ ":include_perfetto_trace_processor_storage",
+ ":include_perfetto_trace_processor_trace_processor",
+ ],
+ deps = [
+ ":protos_perfetto_cloud_trace_processor_lite",
+ ":protos_perfetto_common_lite",
+ ":protos_perfetto_common_zero",
+ ":protos_perfetto_config_android_zero",
+ ":protos_perfetto_config_ftrace_zero",
+ ":protos_perfetto_config_gpu_zero",
+ ":protos_perfetto_config_inode_file_zero",
+ ":protos_perfetto_config_interceptors_zero",
+ ":protos_perfetto_config_power_zero",
+ ":protos_perfetto_config_process_stats_zero",
+ ":protos_perfetto_config_profiling_zero",
+ ":protos_perfetto_config_statsd_zero",
+ ":protos_perfetto_config_sys_stats_zero",
+ ":protos_perfetto_config_system_info_zero",
+ ":protos_perfetto_config_track_event_zero",
+ ":protos_perfetto_config_zero",
+ ":protos_perfetto_trace_android_zero",
+ ":protos_perfetto_trace_chrome_zero",
+ ":protos_perfetto_trace_filesystem_zero",
+ ":protos_perfetto_trace_ftrace_zero",
+ ":protos_perfetto_trace_gpu_zero",
+ ":protos_perfetto_trace_interned_data_zero",
+ ":protos_perfetto_trace_minimal_zero",
+ ":protos_perfetto_trace_non_minimal_zero",
+ ":protos_perfetto_trace_perfetto_zero",
+ ":protos_perfetto_trace_power_zero",
+ ":protos_perfetto_trace_processor_lite",
+ ":protos_perfetto_trace_processor_metrics_impl_zero",
+ ":protos_perfetto_trace_processor_zero",
+ ":protos_perfetto_trace_profiling_zero",
+ ":protos_perfetto_trace_ps_zero",
+ ":protos_perfetto_trace_statsd_zero",
+ ":protos_perfetto_trace_sys_stats_zero",
+ ":protos_perfetto_trace_system_info_zero",
+ ":protos_perfetto_trace_track_event_zero",
+ ":protos_perfetto_trace_translation_zero",
+ ":protos_third_party_pprof_zero",
+ ":protozero",
+ ":src_base_base",
+ ":src_base_version",
+ ":src_trace_processor_containers_containers",
+ ":src_trace_processor_importers_proto_gen_cc_chrome_track_event_descriptor",
+ ":src_trace_processor_importers_proto_gen_cc_config_descriptor",
+ ":src_trace_processor_importers_proto_gen_cc_statsd_atoms_descriptor",
+ ":src_trace_processor_importers_proto_gen_cc_trace_descriptor",
+ ":src_trace_processor_importers_proto_gen_cc_track_event_descriptor",
+ ":src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
+ ":src_trace_processor_metrics_gen_cc_all_webview_metrics_descriptor",
+ ":src_trace_processor_metrics_gen_cc_metrics_descriptor",
+ ":src_trace_processor_metrics_sql_gen_amalgamated_sql_metrics",
+ ":src_trace_processor_prelude_tables_views_tables_views",
+ ":src_trace_processor_stdlib_gen_amalgamated_stdlib",
+ ] + PERFETTO_CONFIG.deps.jsoncpp +
+ PERFETTO_CONFIG.deps.sqlite +
+ PERFETTO_CONFIG.deps.sqlite_ext_percentile +
+ PERFETTO_CONFIG.deps.zlib +
+ PERFETTO_CONFIG.deps.demangle_wrapper,
+ linkstatic = True,
+)
+
# GN target: //src/ipc/protoc_plugin:ipc_plugin
perfetto_cc_binary(
name = "ipc_plugin",
@@ -279,6 +425,7 @@
":src_tracing_common",
":src_tracing_core_core",
":src_tracing_core_service",
+ ":src_tracing_core_zlib_compressor",
":src_tracing_ipc_common",
":src_tracing_ipc_default_socket",
":src_tracing_ipc_producer_producer",
@@ -355,7 +502,7 @@
":protozero",
":src_base_base",
":src_base_version",
- ],
+ ] + PERFETTO_CONFIG.deps.zlib,
linkstatic = True,
)
@@ -387,6 +534,22 @@
],
)
+# GN target: //include/perfetto/ext/base/threading:threading
+perfetto_filegroup(
+ name = "include_perfetto_ext_base_threading_threading",
+ srcs = [
+ "include/perfetto/ext/base/threading/channel.h",
+ "include/perfetto/ext/base/threading/future.h",
+ "include/perfetto/ext/base/threading/future_combinators.h",
+ "include/perfetto/ext/base/threading/poll.h",
+ "include/perfetto/ext/base/threading/spawn.h",
+ "include/perfetto/ext/base/threading/stream.h",
+ "include/perfetto/ext/base/threading/stream_combinators.h",
+ "include/perfetto/ext/base/threading/thread_pool.h",
+ "include/perfetto/ext/base/threading/util.h",
+ ],
+)
+
# GN target: //include/perfetto/ext/base:base
perfetto_filegroup(
name = "include_perfetto_ext_base_base",
@@ -446,6 +609,16 @@
],
)
+# GN target: //include/perfetto/ext/cloud_trace_processor:cloud_trace_processor
+perfetto_filegroup(
+ name = "include_perfetto_ext_cloud_trace_processor_cloud_trace_processor",
+ srcs = [
+ "include/perfetto/ext/cloud_trace_processor/environment.h",
+ "include/perfetto/ext/cloud_trace_processor/orchestrator.h",
+ "include/perfetto/ext/cloud_trace_processor/worker.h",
+ ],
+)
+
# GN target: //include/perfetto/ext/ipc:ipc
perfetto_filegroup(
name = "include_perfetto_ext_ipc_ipc",
@@ -758,6 +931,16 @@
linkstatic = True,
)
+# GN target: //src/base/threading:threading
+perfetto_filegroup(
+ name = "src_base_threading_threading",
+ srcs = [
+ "src/base/threading/spawn.cc",
+ "src/base/threading/stream_combinators.cc",
+ "src/base/threading/thread_pool.cc",
+ ],
+)
+
# GN target: //src/base:base
perfetto_cc_library(
name = "src_base_base",
@@ -849,6 +1032,19 @@
],
)
+# GN target: //src/cloud_trace_processor:sources
+perfetto_filegroup(
+ name = "src_cloud_trace_processor_sources",
+ srcs = [
+ "src/cloud_trace_processor/orchestrator_impl.cc",
+ "src/cloud_trace_processor/orchestrator_impl.h",
+ "src/cloud_trace_processor/trace_processor_wrapper.cc",
+ "src/cloud_trace_processor/trace_processor_wrapper.h",
+ "src/cloud_trace_processor/worker_impl.cc",
+ "src/cloud_trace_processor/worker_impl.h",
+ ],
+)
+
# GN target: //src/ipc:client
perfetto_filegroup(
name = "src_ipc_client",
@@ -1082,17 +1278,20 @@
"src/trace_processor/db/base_id.h",
"src/trace_processor/db/column.cc",
"src/trace_processor/db/column.h",
+ "src/trace_processor/db/column_overlay.cc",
"src/trace_processor/db/column_overlay.h",
"src/trace_processor/db/column_storage.cc",
"src/trace_processor/db/column_storage.h",
"src/trace_processor/db/column_storage_overlay.h",
"src/trace_processor/db/compare.h",
+ "src/trace_processor/db/null_overlay.cc",
"src/trace_processor/db/null_overlay.h",
"src/trace_processor/db/numeric_storage.cc",
"src/trace_processor/db/numeric_storage.h",
"src/trace_processor/db/sorting_overlay.h",
"src/trace_processor/db/storage.cc",
"src/trace_processor/db/storage.h",
+ "src/trace_processor/db/storage_overlay.cc",
"src/trace_processor/db/storage_overlay.h",
"src/trace_processor/db/storage_variants.h",
"src/trace_processor/db/table.cc",
@@ -1588,6 +1787,7 @@
"src/trace_processor/metrics/sql/android/java_heap_histogram.sql",
"src/trace_processor/metrics/sql/android/java_heap_stats.sql",
"src/trace_processor/metrics/sql/android/mem_stats_priority_breakdown.sql",
+ "src/trace_processor/metrics/sql/android/network_activity_template.sql",
"src/trace_processor/metrics/sql/android/p_state.sql",
"src/trace_processor/metrics/sql/android/power_drain_in_watts.sql",
"src/trace_processor/metrics/sql/android/power_profile_data.sql",
@@ -1803,8 +2003,6 @@
"src/trace_processor/prelude/functions/layout_functions.h",
"src/trace_processor/prelude/functions/pprof_functions.cc",
"src/trace_processor/prelude/functions/pprof_functions.h",
- "src/trace_processor/prelude/functions/register_function.cc",
- "src/trace_processor/prelude/functions/register_function.h",
"src/trace_processor/prelude/functions/sqlite3_str_split.cc",
"src/trace_processor/prelude/functions/sqlite3_str_split.h",
"src/trace_processor/prelude/functions/stack_functions.cc",
@@ -1816,6 +2014,15 @@
],
)
+# GN target: //src/trace_processor/prelude/functions:interface
+perfetto_filegroup(
+ name = "src_trace_processor_prelude_functions_interface",
+ srcs = [
+ "src/trace_processor/prelude/functions/sql_function.cc",
+ "src/trace_processor/prelude/functions/sql_function.h",
+ ],
+)
+
# GN target: //src/trace_processor/prelude/operators:operators
perfetto_filegroup(
name = "src_trace_processor_prelude_operators_operators",
@@ -1827,6 +2034,15 @@
],
)
+# GN target: //src/trace_processor/prelude/table_functions:interface
+perfetto_filegroup(
+ name = "src_trace_processor_prelude_table_functions_interface",
+ srcs = [
+ "src/trace_processor/prelude/table_functions/table_function.cc",
+ "src/trace_processor/prelude/table_functions/table_function.h",
+ ],
+)
+
# GN target: //src/trace_processor/prelude/table_functions:table_functions
perfetto_filegroup(
name = "src_trace_processor_prelude_table_functions_table_functions",
@@ -1851,8 +2067,6 @@
"src/trace_processor/prelude/table_functions/experimental_slice_layout.h",
"src/trace_processor/prelude/table_functions/flamegraph_construction_algorithms.cc",
"src/trace_processor/prelude/table_functions/flamegraph_construction_algorithms.h",
- "src/trace_processor/prelude/table_functions/table_function.cc",
- "src/trace_processor/prelude/table_functions/table_function.h",
"src/trace_processor/prelude/table_functions/view.cc",
"src/trace_processor/prelude/table_functions/view.h",
],
@@ -1924,6 +2138,15 @@
],
)
+# GN target: //src/trace_processor/sqlite:query_constraints
+perfetto_filegroup(
+ name = "src_trace_processor_sqlite_query_constraints",
+ srcs = [
+ "src/trace_processor/sqlite/query_constraints.cc",
+ "src/trace_processor/sqlite/query_constraints.h",
+ ],
+)
+
# GN target: //src/trace_processor/sqlite:sqlite
perfetto_filegroup(
name = "src_trace_processor_sqlite_sqlite",
@@ -1931,10 +2154,13 @@
"src/trace_processor/sqlite/db_sqlite_table.cc",
"src/trace_processor/sqlite/db_sqlite_table.h",
"src/trace_processor/sqlite/query_cache.h",
+ "src/trace_processor/sqlite/scoped_db.h",
"src/trace_processor/sqlite/sql_stats_table.cc",
"src/trace_processor/sqlite/sql_stats_table.h",
"src/trace_processor/sqlite/sqlite_engine.cc",
"src/trace_processor/sqlite/sqlite_engine.h",
+ "src/trace_processor/sqlite/sqlite_table.cc",
+ "src/trace_processor/sqlite/sqlite_table.h",
"src/trace_processor/sqlite/sqlite_utils.cc",
"src/trace_processor/sqlite/sqlite_utils.h",
"src/trace_processor/sqlite/stats_table.cc",
@@ -1942,19 +2168,6 @@
],
)
-# GN target: //src/trace_processor/sqlite:sqlite_minimal
-perfetto_filegroup(
- name = "src_trace_processor_sqlite_sqlite_minimal",
- srcs = [
- "src/trace_processor/sqlite/query_constraints.cc",
- "src/trace_processor/sqlite/query_constraints.h",
- "src/trace_processor/sqlite/scoped_db.h",
- "src/trace_processor/sqlite/sqlite_table.cc",
- "src/trace_processor/sqlite/sqlite_table.h",
- "src/trace_processor/sqlite/sqlite_utils.h",
- ],
-)
-
# GN target: //src/trace_processor/stdlib/android/startup:startup
perfetto_filegroup(
name = "src_trace_processor_stdlib_android_startup_startup",
@@ -1971,10 +2184,13 @@
name = "src_trace_processor_stdlib_android_android",
srcs = [
"src/trace_processor/stdlib/android/battery.sql",
+ "src/trace_processor/stdlib/android/battery_stats.sql",
"src/trace_processor/stdlib/android/binder.sql",
"src/trace_processor/stdlib/android/monitor_contention.sql",
+ "src/trace_processor/stdlib/android/network_packets.sql",
"src/trace_processor/stdlib/android/process_metadata.sql",
"src/trace_processor/stdlib/android/slices.sql",
+ "src/trace_processor/stdlib/android/statsd.sql",
],
)
@@ -1982,6 +2198,7 @@
perfetto_filegroup(
name = "src_trace_processor_stdlib_chrome_chrome_sql",
srcs = [
+ "src/trace_processor/stdlib/chrome/chrome_scrolls.sql",
"src/trace_processor/stdlib/chrome/cpu_powerups.sql",
],
)
@@ -2632,6 +2849,15 @@
],
)
+# GN target: //src/tracing/core:zlib_compressor
+perfetto_filegroup(
+ name = "src_tracing_core_zlib_compressor",
+ srcs = [
+ "src/tracing/core/zlib_compressor.cc",
+ "src/tracing/core/zlib_compressor.h",
+ ],
+)
+
# GN target: //src/tracing/ipc/consumer:consumer
perfetto_filegroup(
name = "src_tracing_ipc_consumer_consumer",
@@ -3044,6 +3270,31 @@
],
)
+# GN target: //protos/perfetto/cloud_trace_processor:lite
+perfetto_cc_proto_library(
+ name = "protos_perfetto_cloud_trace_processor_lite",
+ deps = [
+ ":protos_perfetto_cloud_trace_processor_protos",
+ ],
+)
+
+# GN target: //protos/perfetto/cloud_trace_processor:source_set
+perfetto_proto_library(
+ name = "protos_perfetto_cloud_trace_processor_protos",
+ srcs = [
+ "protos/perfetto/cloud_trace_processor/common.proto",
+ "protos/perfetto/cloud_trace_processor/orchestrator.proto",
+ "protos/perfetto/cloud_trace_processor/worker.proto",
+ ],
+ visibility = [
+ PERFETTO_CONFIG.proto_library_visibility,
+ ],
+ deps = [
+ ":protos_perfetto_common_protos",
+ ":protos_perfetto_trace_processor_protos",
+ ],
+)
+
# GN target: //protos/perfetto/common:cpp
perfetto_cc_protocpp_library(
name = "protos_perfetto_common_cpp",
@@ -3052,6 +3303,14 @@
],
)
+# GN target: //protos/perfetto/common:lite
+perfetto_cc_proto_library(
+ name = "protos_perfetto_common_lite",
+ deps = [
+ ":protos_perfetto_common_protos",
+ ],
+)
+
# GN target: //protos/perfetto/common:source_set
perfetto_proto_library(
name = "protos_perfetto_common_protos",
@@ -4193,6 +4452,14 @@
],
)
+# GN target: //protos/perfetto/trace_processor:lite
+perfetto_cc_proto_library(
+ name = "protos_perfetto_trace_processor_lite",
+ deps = [
+ ":protos_perfetto_trace_processor_protos",
+ ],
+)
+
# GN target: //protos/perfetto/trace_processor:metrics_impl_source_set
perfetto_proto_library(
name = "protos_perfetto_trace_processor_metrics_impl_protos",
@@ -4753,12 +5020,14 @@
":src_trace_processor_metatrace",
":src_trace_processor_metrics_metrics",
":src_trace_processor_prelude_functions_functions",
+ ":src_trace_processor_prelude_functions_interface",
":src_trace_processor_prelude_operators_operators",
+ ":src_trace_processor_prelude_table_functions_interface",
":src_trace_processor_prelude_table_functions_table_functions",
":src_trace_processor_prelude_table_functions_tables",
":src_trace_processor_sorter_sorter",
+ ":src_trace_processor_sqlite_query_constraints",
":src_trace_processor_sqlite_sqlite",
- ":src_trace_processor_sqlite_sqlite_minimal",
":src_trace_processor_storage_minimal",
":src_trace_processor_storage_storage",
":src_trace_processor_tables_tables",
@@ -4907,14 +5176,16 @@
":src_trace_processor_metatrace",
":src_trace_processor_metrics_metrics",
":src_trace_processor_prelude_functions_functions",
+ ":src_trace_processor_prelude_functions_interface",
":src_trace_processor_prelude_operators_operators",
+ ":src_trace_processor_prelude_table_functions_interface",
":src_trace_processor_prelude_table_functions_table_functions",
":src_trace_processor_prelude_table_functions_tables",
":src_trace_processor_rpc_httpd",
":src_trace_processor_rpc_rpc",
":src_trace_processor_sorter_sorter",
+ ":src_trace_processor_sqlite_query_constraints",
":src_trace_processor_sqlite_sqlite",
- ":src_trace_processor_sqlite_sqlite_minimal",
":src_trace_processor_storage_minimal",
":src_trace_processor_storage_storage",
":src_trace_processor_tables_tables",
@@ -5120,12 +5391,14 @@
":src_trace_processor_metatrace",
":src_trace_processor_metrics_metrics",
":src_trace_processor_prelude_functions_functions",
+ ":src_trace_processor_prelude_functions_interface",
":src_trace_processor_prelude_operators_operators",
+ ":src_trace_processor_prelude_table_functions_interface",
":src_trace_processor_prelude_table_functions_table_functions",
":src_trace_processor_prelude_table_functions_tables",
":src_trace_processor_sorter_sorter",
+ ":src_trace_processor_sqlite_query_constraints",
":src_trace_processor_sqlite_sqlite",
- ":src_trace_processor_sqlite_sqlite_minimal",
":src_trace_processor_storage_minimal",
":src_trace_processor_storage_storage",
":src_trace_processor_tables_tables",
diff --git a/CHANGELOG b/CHANGELOG
index 6e371a4..107a26b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,9 @@
Unreleased:
Tracing service and probes:
+ * Compression has been moved from perfetto_cmd to traced. Now compression is
+ supported even with write_into_file. The `compress_from_cli` config option
+ can be used to restore the old behavior.
+ Trace Processor:
*
UI:
*
@@ -10,6 +14,8 @@
Tracing service and probes:
* --continuous-dump in tools/java_heap_dump now keeps recording until it
receives CTRL+C.
+ * Add CLONE_SNAPSHOT triggers for non-destructive snapshots of the trace
+ buffer without tracing interruption.
Trace Processor:
*
UI:
diff --git a/docs/contributing/perfetto-in-the-press.md b/docs/contributing/perfetto-in-the-press.md
index 108849a..4546bd6 100644
--- a/docs/contributing/perfetto-in-the-press.md
+++ b/docs/contributing/perfetto-in-the-press.md
@@ -2,6 +2,8 @@
This a partial collection of the talks, blogposts, presentations, and articles that mention Perfetto.
+- [Google IO 2023 - What's new in Dart and Flutter](https://youtu.be/yRlwOdCK7Ho?t=798)
+- [Google IO 2023 - Debugging Jetpack Compose](https://youtu.be/Kp-aiSU8qCU?t=1092)
- [Performance: Perfetto Traceviewer - MAD Skills](https://www.youtube.com/watch?v=phhLFicMacY)
"On this episode of the MAD Skills series on Performance, Android Performance Engineer Carmen Jackson discusses the Perfetto traceviewer, an alternative to Android Studio for viewing system traces."
- [Performance and optimisation on the Meta Quest Platform](https://m.facebook.com/RealityLabs/videos/performance-and-optimization-on-meta-quest-platform/488126049869673/)
diff --git a/docs/images/enable-profile-flame-graph.png b/docs/images/enable-profile-flame-graph.png
deleted file mode 100644
index 642ce73..0000000
--- a/docs/images/enable-profile-flame-graph.png
+++ /dev/null
Binary files differ
diff --git a/docs/quickstart/callstack-sampling.md b/docs/quickstart/callstack-sampling.md
index e5da5b2..cb47edc 100644
--- a/docs/quickstart/callstack-sampling.md
+++ b/docs/quickstart/callstack-sampling.md
@@ -119,11 +119,6 @@
## View profile
-Visualizing callstacks in the Perfetto UI is currently disabled behind a
-flag. Please enable it before proceeding further:
-
-
-
Upload the `raw-trace` or `symbolized-trace` file from the output directory to
the [Perfetto UI](https://ui.perfetto.dev) and click and drag over one or more
of the diamond markers in the UI track named "Perf Samples" for the processes
diff --git a/docs/quickstart/chrome-tracing.md b/docs/quickstart/chrome-tracing.md
index 4e17172..6786b4d 100644
--- a/docs/quickstart/chrome-tracing.md
+++ b/docs/quickstart/chrome-tracing.md
@@ -4,6 +4,8 @@
> To record traces from Chrome on Android, follow the [instructions for recording Android system traces](/docs/quickstart/android-tracing.md) and enable the Chrome probe.
+>> If you are using [user build of Android](https://source.android.com/docs/setup/build/building#lunch), you'll have to enable integration with system Perfetto by switching chrome://flags#enable-perfetto-system-tracing to "Enabled" and restarting Chrome.
+
## Recording a trace
1. Navigate to [ui.perfetto.dev](https://ui.perfetto.dev/) and select **"Record new trace"** from the left menu.
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index 6edf379..749c2ee 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -289,6 +289,10 @@
"-Wno-unused-parameter",
"-Wno-shadow-field-in-constructor",
"-Wno-zero-as-null-pointer-constant",
+
+ # Fixed in upstream protobuf v3.22.0
+ # d37cbfd4485f("Update inlined_string_field.h"), but we don't have that.
+ "-Wno-undef",
]
}
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index b778d88..579fc0f 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -296,8 +296,9 @@
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).
+ # Enables Zlib support. This is used to compress traces (by the tracing
+ # service and by the "perfetto" cmdline client) and to decompress traces (by
+ # trace_processor).
enable_perfetto_zlib =
(enable_perfetto_trace_processor && !build_with_chromium) ||
enable_perfetto_platform_services
diff --git a/include/perfetto/ext/tracing/core/consumer.h b/include/perfetto/ext/tracing/core/consumer.h
index 7a7d81a..f55b810 100644
--- a/include/perfetto/ext/tracing/core/consumer.h
+++ b/include/perfetto/ext/tracing/core/consumer.h
@@ -20,6 +20,7 @@
#include <vector>
#include "perfetto/base/export.h"
+#include "perfetto/ext/base/uuid.h"
#include "perfetto/ext/tracing/core/basic_types.h"
#include "perfetto/ext/tracing/core/observable_events.h"
#include "perfetto/tracing/core/forward_decls.h"
@@ -81,7 +82,12 @@
// Called back by the Service (or transport layer) after invoking
// TracingService::ConsumerEndpoint::CloneSession().
// TODO(primiano): make pure virtual after various 3way patches.
- virtual void OnSessionCloned(bool success, const std::string& error);
+ struct OnSessionClonedArgs {
+ bool success;
+ std::string error;
+ base::Uuid uuid; // UUID of the cloned session.
+ };
+ virtual void OnSessionCloned(const OnSessionClonedArgs&);
};
} // namespace perfetto
diff --git a/include/perfetto/ext/tracing/core/tracing_service.h b/include/perfetto/ext/tracing/core/tracing_service.h
index 82e53f7..b82a96a 100644
--- a/include/perfetto/ext/tracing/core/tracing_service.h
+++ b/include/perfetto/ext/tracing/core/tracing_service.h
@@ -28,6 +28,7 @@
#include "perfetto/ext/base/sys_types.h"
#include "perfetto/ext/tracing/core/basic_types.h"
#include "perfetto/ext/tracing/core/shared_memory.h"
+#include "perfetto/ext/tracing/core/trace_packet.h"
#include "perfetto/tracing/buffer_exhausted_policy.h"
#include "perfetto/tracing/core/forward_decls.h"
@@ -253,6 +254,14 @@
virtual void SaveTraceForBugreport(SaveTraceForBugreportCallback) = 0;
}; // class ConsumerEndpoint.
+struct PERFETTO_EXPORT_COMPONENT TracingServiceInitOpts {
+ // Function used by tracing service to compress packets. Takes a pointer to
+ // a vector of TracePackets and replaces the packets in the vector with
+ // compressed ones.
+ using CompressorFn = void (*)(std::vector<TracePacket>*);
+ CompressorFn compressor_fn = nullptr;
+};
+
// The public API of the tracing Service business logic.
//
// Exposed to:
@@ -267,6 +276,7 @@
public:
using ProducerEndpoint = perfetto::ProducerEndpoint;
using ConsumerEndpoint = perfetto::ConsumerEndpoint;
+ using InitOpts = TracingServiceInitOpts;
// Default sizes used by the service implementation and client library.
static constexpr size_t kDefaultShmPageSize = 4096ul;
@@ -286,10 +296,12 @@
kDisabled
};
- // Implemented in src/core/tracing_service_impl.cc .
+ // Implemented in src/core/tracing_service_impl.cc . CompressorFn can be
+ // nullptr, in which case TracingService will not support compression.
static std::unique_ptr<TracingService> CreateInstance(
std::unique_ptr<SharedMemory::Factory>,
- base::TaskRunner*);
+ base::TaskRunner*,
+ InitOpts init_opts = {});
virtual ~TracingService();
diff --git a/include/perfetto/ext/tracing/ipc/service_ipc_host.h b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
index 5c51c4a..b24ccb5 100644
--- a/include/perfetto/ext/tracing/ipc/service_ipc_host.h
+++ b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
@@ -23,6 +23,7 @@
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/ext/tracing/core/tracing_service.h"
namespace perfetto {
namespace base {
@@ -33,8 +34,6 @@
class Host;
} // namespace ipc
-class TracingService;
-
// Creates an instance of the service (business logic + UNIX socket transport).
// Exposed to:
// The code in the tracing client that will host the service e.g., traced.
@@ -42,7 +41,9 @@
// src/tracing/ipc/service/service_ipc_host_impl.cc
class PERFETTO_EXPORT_COMPONENT ServiceIPCHost {
public:
- static std::unique_ptr<ServiceIPCHost> CreateInstance(base::TaskRunner*);
+ static std::unique_ptr<ServiceIPCHost> CreateInstance(
+ base::TaskRunner*,
+ TracingService::InitOpts = {});
virtual ~ServiceIPCHost();
// Start listening on the Producer & Consumer ports. Returns false in case of
diff --git a/include/perfetto/protozero/proto_decoder.h b/include/perfetto/protozero/proto_decoder.h
index 2210532..c27fcad 100644
--- a/include/perfetto/protozero/proto_decoder.h
+++ b/include/perfetto/protozero/proto_decoder.h
@@ -340,7 +340,8 @@
uint32_t field_id,
bool* parse_error_location) const {
const Field& field = Get(field_id);
- if (field.valid()) {
+ if (field.valid() &&
+ field.type() == proto_utils::ProtoWireType::kLengthDelimited) {
return PackedRepeatedFieldIterator<wire_type, cpp_type>(
field.data(), field.size(), parse_error_location);
}
diff --git a/include/perfetto/tracing/core/trace_config.h b/include/perfetto/tracing/core/trace_config.h
index 3e2a830..e9807ab 100644
--- a/include/perfetto/tracing/core/trace_config.h
+++ b/include/perfetto/tracing/core/trace_config.h
@@ -25,4 +25,16 @@
#include "protos/perfetto/config/trace_config.gen.h"
+namespace perfetto {
+
+inline TraceConfig::TriggerConfig::TriggerMode GetTriggerMode(
+ const TraceConfig& cfg) {
+ auto mode = cfg.trigger_config().trigger_mode();
+ if (cfg.trigger_config().use_clone_snapshot_if_available())
+ mode = TraceConfig::TriggerConfig::CLONE_SNAPSHOT;
+ return mode;
+}
+
+} // namespace perfetto
+
#endif // INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
diff --git a/include/perfetto/tracing/data_source.h b/include/perfetto/tracing/data_source.h
index 95036d1..26525fa 100644
--- a/include/perfetto/tracing/data_source.h
+++ b/include/perfetto/tracing/data_source.h
@@ -105,7 +105,7 @@
};
virtual void OnStart(const StartArgs&);
- class StopArgs {
+ class PERFETTO_EXPORT_COMPONENT StopArgs {
public:
virtual ~StopArgs();
@@ -190,6 +190,22 @@
}
};
+// Holds the type for a DataSource. Accessed by the static Trace() method
+// fastpaths. This allows redefinitions under a component where a component
+// specific export macro is used.
+// Due to C2086 (redefinition) error on MSVC/clang-cl, internal::DataSourceType
+// can't be a static data member. To avoid explicit specialization after
+// instantiation error, type() needs to be in a template helper class that's
+// instantiated independently from DataSource. See b/280777748.
+template <typename DerivedDataSource,
+ typename DataSourceTraits = DefaultDataSourceTraits>
+struct DataSourceHelper {
+ static internal::DataSourceType& type() {
+ static perfetto::internal::DataSourceType type_;
+ return type_;
+ }
+};
+
// Templated base class meant to be derived by embedders to create a custom data
// source. DerivedDataSource must be the type of the derived class itself, e.g.:
// class MyDataSource : public DataSource<MyDataSource> {...}.
@@ -200,6 +216,7 @@
typename DataSourceTraits = DefaultDataSourceTraits>
class DataSource : public DataSourceBase {
struct DefaultTracePointTraits;
+ using Helper = DataSourceHelper<DerivedDataSource, DataSourceTraits>;
public:
// The BufferExhaustedPolicy to use for TraceWriters of this DataSource.
@@ -286,7 +303,8 @@
// validity before using it. After checking, the handle is guaranteed to
// remain valid until the handle goes out of scope.
LockedHandle<DerivedDataSource> GetDataSourceLocked() const {
- auto* internal_state = type_.static_state()->TryGet(instance_index_);
+ auto* internal_state =
+ Helper::type().static_state()->TryGet(instance_index_);
if (!internal_state)
return LockedHandle<DerivedDataSource>();
std::unique_lock<std::recursive_mutex> lock(internal_state->lock);
@@ -304,7 +322,7 @@
typename DataSourceTraits::IncrementalStateType* GetIncrementalState() {
return static_cast<typename DataSourceTraits::IncrementalStateType*>(
- type_.GetIncrementalState(tls_inst_, instance_index_));
+ Helper::type().GetIncrementalState(tls_inst_, instance_index_));
}
private:
@@ -382,20 +400,20 @@
typename Traits::TracePointData trace_point_data = {}) {
PERFETTO_DCHECK(cached_instances);
- if (!type_.TracePrologue<DataSourceTraits, Traits>(
+ if (!Helper::type().template TracePrologue<DataSourceTraits, Traits>(
&tls_state_, &cached_instances, trace_point_data)) {
return;
}
for (internal::DataSourceType::InstancesIterator it =
- type_.BeginIteration<Traits>(cached_instances, tls_state_,
- trace_point_data);
- it.instance;
- type_.NextIteration<Traits>(&it, tls_state_, trace_point_data)) {
+ Helper::type().template BeginIteration<Traits>(
+ cached_instances, tls_state_, trace_point_data);
+ it.instance; Helper::type().template NextIteration<Traits>(
+ &it, tls_state_, trace_point_data)) {
tracing_fn(TraceContext(it.instance, it.i));
}
- type_.TraceEpilogue(tls_state_);
+ Helper::type().TraceEpilogue(tls_state_);
}
// Registers the data source on all tracing backends, including ones that
@@ -413,7 +431,6 @@
const Args&... constructor_args) {
// Silences -Wunused-variable warning in case the trace method is not used
// by the translation unit that declares the data source.
- (void)type_;
(void)tls_state_;
auto factory = [constructor_args...]() {
@@ -423,7 +440,7 @@
internal::DataSourceParams params{
DerivedDataSource::kSupportsMultipleInstances,
DerivedDataSource::kRequiresCallbacksUnderLock};
- return type_.Register(
+ return Helper::type().Register(
descriptor, factory, params, DerivedDataSource::kBufferExhaustedPolicy,
GetCreateTlsFn(
static_cast<typename DataSourceTraits::TlsStateType*>(nullptr)),
@@ -435,7 +452,7 @@
// Updates the data source descriptor.
static void UpdateDescriptor(const DataSourceDescriptor& descriptor) {
- type_.UpdateDescriptor(descriptor);
+ Helper::type().UpdateDescriptor(descriptor);
}
private:
@@ -456,7 +473,7 @@
// implement per-category enabled states.
struct TracePointData {};
static constexpr std::atomic<uint32_t>* GetActiveInstances(TracePointData) {
- return type_.valid_instances();
+ return Helper::type().valid_instances();
}
};
@@ -506,10 +523,6 @@
return nullptr;
}
- // The type of this data source. Accessed by the static Trace() method
- // fastpaths.
- static internal::DataSourceType type_;
-
// This TLS object is a cached raw pointer and has deliberately no destructor.
// The Platform implementation is supposed to create and manage the lifetime
// of the Platform::ThreadLocalObject and take care of destroying it.
@@ -522,9 +535,6 @@
// static
template <typename T, typename D>
-internal::DataSourceType DataSource<T, D>::type_;
-// static
-template <typename T, typename D>
PERFETTO_THREAD_LOCAL internal::DataSourceThreadLocalState*
DataSource<T, D>::tls_state_;
@@ -547,16 +557,11 @@
// where a component specific export macro is used.
#define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(attrs, ...) \
template <> \
- attrs perfetto::internal::DataSourceType \
- perfetto::DataSource<__VA_ARGS__>::type_
+ attrs perfetto::internal::DataSourceType& \
+ perfetto::DataSourceHelper<__VA_ARGS__>::type()
// This macro must be used once for each data source in one source file to
// allocate static storage for the data source's static state.
-//
-// Note: if MSVC fails with a C2086 (redefinition) error here, use the
-// permissive- flag to enable standards-compliant mode. See
-// https://developercommunity.visualstudio.com/content/problem/319447/
-// explicit-specialization-of-static-data-member-inco.html.
#define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(...) \
PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS( \
PERFETTO_COMPONENT_EXPORT, __VA_ARGS__)
@@ -566,7 +571,11 @@
// where a component specific export macro is used.
#define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(attrs, ...) \
template <> \
- attrs perfetto::internal::DataSourceType \
- perfetto::DataSource<__VA_ARGS__>::type_ {}
+ perfetto::internal::DataSourceType& \
+ perfetto::DataSourceHelper<__VA_ARGS__>::type() { \
+ static perfetto::internal::DataSourceType type_; \
+ return type_; \
+ } \
+ PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
#endif // INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
diff --git a/include/perfetto/tracing/interceptor.h b/include/perfetto/tracing/interceptor.h
index b800cb3..637c8bf 100644
--- a/include/perfetto/tracing/interceptor.h
+++ b/include/perfetto/tracing/interceptor.h
@@ -187,7 +187,7 @@
// To define your own state, subclass this with the same name in the
// interceptor class. A reference to the state can then be looked up through
// context.GetThreadLocalState() in the trace packet interceptor function.
- class ThreadLocalState {
+ class PERFETTO_EXPORT_COMPONENT ThreadLocalState {
public:
virtual ~ThreadLocalState();
};
diff --git a/protos/perfetto/common/observable_events.proto b/protos/perfetto/common/observable_events.proto
index 0bde227..85767a6 100644
--- a/protos/perfetto/common/observable_events.proto
+++ b/protos/perfetto/common/observable_events.proto
@@ -35,6 +35,11 @@
// Introduced in Android 11 (R).
TYPE_ALL_DATA_SOURCES_STARTED = 2;
+ // When a tracing session has one or more triggers of type CLONE_SNAPSHOT
+ // and a matching trigger is hit, the service will send this notification to
+ // the consumer after |stop_delay_ms|.
+ TYPE_CLONE_TRIGGER_HIT = 4;
+
// Note: internally these are used as OR flags. Next values: 4, 8, 16, ...
// TODO(eseckler): Extend this for producer & data source registrations.
@@ -52,6 +57,15 @@
optional DataSourceInstanceState state = 3;
}
+ message CloneTriggerHit {
+ // The TracingSessionID of the original tracing session which had a
+ // CLONE_SNAPSHOT trigger defined. This is necessary just because the
+ // consumer has no idea of what is the TSID of its own tracing session and
+ // there is no other good way to plumb it.
+ optional int64 tracing_session_id = 1;
+ }
+
repeated DataSourceInstanceStateChange instance_state_changes = 1;
optional bool all_data_sources_started = 2;
+ optional CloneTriggerHit clone_trigger_hit = 3;
}
diff --git a/protos/perfetto/common/tracing_service_capabilities.proto b/protos/perfetto/common/tracing_service_capabilities.proto
index 123f9bf..308f18d 100644
--- a/protos/perfetto/common/tracing_service_capabilities.proto
+++ b/protos/perfetto/common/tracing_service_capabilities.proto
@@ -35,4 +35,7 @@
// Whether the service supports TraceConfig.output_path (for asking traced to
// create the output file instead of passing a file descriptor).
optional bool has_trace_config_output_path = 3;
+
+ // Whether the service supports CloneSession and CLONE_SNAPSHOT triggers.
+ optional bool has_clone_session = 4;
}
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 7b1171f..85f1de7 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -833,6 +833,7 @@
// If > 0 samples counters (see process_stats.proto) from
// /proc/pid/status and oom_score_adj every X ms.
+ // It will also sample /proc/pid/smaps_rollup if scan_smaps_rollup = true.
// This is required to be > 100ms to avoid excessive CPU usage.
// TODO(primiano): add CPU cost for change this value.
optional uint32 proc_stats_poll_ms = 4;
@@ -861,6 +862,10 @@
// new fds opened after initially scanning a process will not be
// recognized.
optional bool resolve_process_fds = 9;
+
+ // If enabled memory stats from /proc/pid/smaps_rollup will be included
+ // in process stats.
+ optional bool scan_smaps_rollup = 10;
}
// End of protos/perfetto/config/process_stats/process_stats_config.proto
@@ -2700,7 +2705,7 @@
// It contains the general config for the logging buffer(s) and the configs for
// all the data source being enabled.
//
-// Next id: 37.
+// Next id: 38.
message TraceConfig {
message BufferConfig {
optional uint32 size_kb = 1;
@@ -2968,12 +2973,35 @@
// consumer.
STOP_TRACING = 2;
- // NOTE: do not add new enum values here because of a subtle backward
- // compat bug which might cause indefinite tracing on older versions of
- // the service. See b/274931668 .
+ // When this mode is chosen, this causes a snapshot of the current tracing
+ // session to be created after |stop_delay_ms| while the current tracing
+ // session continues undisturbed (% an extra flush). This mode can be
+ // used only when the tracing session is handled by the "perfetto" cmdline
+ // client (which is true in 90% of cases). Part of the business logic
+ // necessary for this behavior, and ensuing file handling, lives in
+ // perfetto_cmd.cc . On other consumers, this causes only a notification
+ // of the trigger through a CloneTriggerHit ObservableEvent. The custom
+ // consumer is supposed to call CloneSession() itself after the event.
+ // Use use_clone_snapshot_if_available=true when targeting older versions
+ // of perfetto.
+ CLONE_SNAPSHOT = 3;
+
+ // NOTE: CLONE_SNAPSHOT should be used only when we targeting Android U+
+ // (14+) / Perfetto v34+. A bug in older versions of the tracing service
+ // might cause indefinitely long tracing sessions (see b/274931668).
}
optional TriggerMode trigger_mode = 1;
+ // This flag is really a workaround for b/274931668. This is needed only
+ // when deploying configs to different versions of the tracing service.
+ // When this is set to true this has the same effect of setting trigger_mode
+ // to CLONE_SNAPSHOT on newer versions of the service. This boolean has been
+ // introduced to allow to have configs that use CLONE_SNAPSHOT on newer
+ // versions of Android and fall back to STOP_TRACING on older versions where
+ // CLONE_SNAPSHOT did not exist.
+ // When using this flag, trigger_mode must be set to STOP_TRACING.
+ optional bool use_clone_snapshot_if_available = 4;
+
message Trigger {
// The producer must specify this name to activate the trigger.
optional string name = 1;
@@ -2985,6 +3013,8 @@
// After a trigger is received either in START_TRACING or STOP_TRACING
// mode then the trace will end |stop_delay_ms| after triggering.
+ // In CLONE_SNAPSHOT mode, this is the delay between the trigger and the
+ // snapshot.
// If |prefer_suspend_clock_for_duration| is set, the duration will be
// based on wall-clock, counting also time in suspend.
optional uint32 stop_delay_ms = 3;
@@ -3064,6 +3094,11 @@
}
optional CompressionType compression_type = 24;
+ // Use the legacy codepath that compresses from perfetto_cmd.cc instead of
+ // using the new codepath that compresses from tracing_service_impl.cc. This
+ // will be removed in the future.
+ optional bool compress_from_cli = 37;
+
// Android-only. Not for general use. If set, saves the trace into an
// incident. This field is read by perfetto_cmd, rather than the tracing
// service. This field must be set when passing the --upload flag to
diff --git a/protos/perfetto/config/process_stats/process_stats_config.proto b/protos/perfetto/config/process_stats/process_stats_config.proto
index d71e7d3..239513f 100644
--- a/protos/perfetto/config/process_stats/process_stats_config.proto
+++ b/protos/perfetto/config/process_stats/process_stats_config.proto
@@ -41,6 +41,7 @@
// If > 0 samples counters (see process_stats.proto) from
// /proc/pid/status and oom_score_adj every X ms.
+ // It will also sample /proc/pid/smaps_rollup if scan_smaps_rollup = true.
// This is required to be > 100ms to avoid excessive CPU usage.
// TODO(primiano): add CPU cost for change this value.
optional uint32 proc_stats_poll_ms = 4;
@@ -69,4 +70,8 @@
// new fds opened after initially scanning a process will not be
// recognized.
optional bool resolve_process_fds = 9;
+
+ // If enabled memory stats from /proc/pid/smaps_rollup will be included
+ // in process stats.
+ optional bool scan_smaps_rollup = 10;
}
diff --git a/protos/perfetto/config/trace_config.proto b/protos/perfetto/config/trace_config.proto
index 04e637c..4fe3ea9 100644
--- a/protos/perfetto/config/trace_config.proto
+++ b/protos/perfetto/config/trace_config.proto
@@ -26,7 +26,7 @@
// It contains the general config for the logging buffer(s) and the configs for
// all the data source being enabled.
//
-// Next id: 37.
+// Next id: 38.
message TraceConfig {
message BufferConfig {
optional uint32 size_kb = 1;
@@ -294,12 +294,35 @@
// consumer.
STOP_TRACING = 2;
- // NOTE: do not add new enum values here because of a subtle backward
- // compat bug which might cause indefinite tracing on older versions of
- // the service. See b/274931668 .
+ // When this mode is chosen, this causes a snapshot of the current tracing
+ // session to be created after |stop_delay_ms| while the current tracing
+ // session continues undisturbed (% an extra flush). This mode can be
+ // used only when the tracing session is handled by the "perfetto" cmdline
+ // client (which is true in 90% of cases). Part of the business logic
+ // necessary for this behavior, and ensuing file handling, lives in
+ // perfetto_cmd.cc . On other consumers, this causes only a notification
+ // of the trigger through a CloneTriggerHit ObservableEvent. The custom
+ // consumer is supposed to call CloneSession() itself after the event.
+ // Use use_clone_snapshot_if_available=true when targeting older versions
+ // of perfetto.
+ CLONE_SNAPSHOT = 3;
+
+ // NOTE: CLONE_SNAPSHOT should be used only when we targeting Android U+
+ // (14+) / Perfetto v34+. A bug in older versions of the tracing service
+ // might cause indefinitely long tracing sessions (see b/274931668).
}
optional TriggerMode trigger_mode = 1;
+ // This flag is really a workaround for b/274931668. This is needed only
+ // when deploying configs to different versions of the tracing service.
+ // When this is set to true this has the same effect of setting trigger_mode
+ // to CLONE_SNAPSHOT on newer versions of the service. This boolean has been
+ // introduced to allow to have configs that use CLONE_SNAPSHOT on newer
+ // versions of Android and fall back to STOP_TRACING on older versions where
+ // CLONE_SNAPSHOT did not exist.
+ // When using this flag, trigger_mode must be set to STOP_TRACING.
+ optional bool use_clone_snapshot_if_available = 4;
+
message Trigger {
// The producer must specify this name to activate the trigger.
optional string name = 1;
@@ -311,6 +334,8 @@
// After a trigger is received either in START_TRACING or STOP_TRACING
// mode then the trace will end |stop_delay_ms| after triggering.
+ // In CLONE_SNAPSHOT mode, this is the delay between the trigger and the
+ // snapshot.
// If |prefer_suspend_clock_for_duration| is set, the duration will be
// based on wall-clock, counting also time in suspend.
optional uint32 stop_delay_ms = 3;
@@ -390,6 +415,11 @@
}
optional CompressionType compression_type = 24;
+ // Use the legacy codepath that compresses from perfetto_cmd.cc instead of
+ // using the new codepath that compresses from tracing_service_impl.cc. This
+ // will be removed in the future.
+ optional bool compress_from_cli = 37;
+
// Android-only. Not for general use. If set, saves the trace into an
// incident. This field is read by perfetto_cmd, rather than the tracing
// service. This field must be set when passing the --upload flag to
diff --git a/protos/perfetto/ipc/consumer_port.proto b/protos/perfetto/ipc/consumer_port.proto
index d5a4025..2fdc919 100644
--- a/protos/perfetto/ipc/consumer_port.proto
+++ b/protos/perfetto/ipc/consumer_port.proto
@@ -289,4 +289,8 @@
// the details about the failure.
optional bool success = 1;
optional string error = 2;
+
+ // The UUID of the cloned session.
+ optional int64 uuid_msb = 3;
+ optional int64 uuid_lsb = 4;
}
diff --git a/protos/perfetto/metrics/android/binder_metric.proto b/protos/perfetto/metrics/android/binder_metric.proto
index 5c4e66f..36c1abb 100644
--- a/protos/perfetto/metrics/android/binder_metric.proto
+++ b/protos/perfetto/metrics/android/binder_metric.proto
@@ -56,6 +56,9 @@
optional uint32 client_tid = 15;
optional uint32 server_tid = 16;
+
+ optional uint32 client_pid = 17;
+ optional uint32 server_pid = 18;
}
message ThreadStateBreakdown {
diff --git a/protos/perfetto/metrics/android/java_heap_stats.proto b/protos/perfetto/metrics/android/java_heap_stats.proto
index 2579888..10a0b8b 100644
--- a/protos/perfetto/metrics/android/java_heap_stats.proto
+++ b/protos/perfetto/metrics/android/java_heap_stats.proto
@@ -26,7 +26,7 @@
optional int64 obj_count = 3;
}
- // Next id: 10
+ // Next id: 11
message Sample {
optional int64 ts = 1;
// Size of the Java heap in bytes
@@ -45,6 +45,8 @@
// ART root objects
repeated HeapRoots roots = 7;
+ // OOM adjustment score
+ optional int64 oom_score_adj = 10;
}
// Heap stats per process. One sample per dump (can be > 1 if continuous
diff --git a/protos/perfetto/metrics/android/monitor_contention_metric.proto b/protos/perfetto/metrics/android/monitor_contention_metric.proto
index 91122eb..00585d8 100644
--- a/protos/perfetto/metrics/android/monitor_contention_metric.proto
+++ b/protos/perfetto/metrics/android/monitor_contention_metric.proto
@@ -21,28 +21,38 @@
// This metric provides information about the monitor contention graph in a
// trace
message AndroidMonitorContentionMetric {
+ // Next field id: 24
message Node {
+ // Global context
optional int64 node_parent_id = 1;
optional int64 node_id = 2;
optional int64 ts = 3;
optional int64 dur = 4;
- optional string blocking_method = 5;
- optional string blocked_method = 6;
- optional string short_blocking_method = 7;
- optional string short_blocked_method = 8;
- optional string blocking_src = 9;
- optional string blocked_src = 10;
- optional uint32 waiter_count = 11;
- optional string blocked_thread_name = 12;
- optional string blocking_thread_name = 13;
optional string process_name = 14;
- optional bool is_blocked_thread_main = 15;
- optional bool is_blocking_thread_main = 16;
- optional int64 binder_reply_ts = 17;
- optional uint32 binder_reply_tid = 18;
-
+ optional uint32 pid = 23;
+ optional uint32 waiter_count = 11;
repeated ThreadStateBreakdown thread_states = 19;
repeated BlockedFunctionBreakdown blocked_functions = 20;
+
+ // Blocking context
+ optional string blocking_method = 5;
+ optional string short_blocking_method = 7;
+ optional string blocking_src = 9;
+ optional string blocking_thread_name = 13;
+ optional bool is_blocking_thread_main = 16;
+ optional uint32 blocking_thread_tid = 22;
+
+ // Blocked context
+ optional string blocked_method = 6;
+ optional string short_blocked_method = 8;
+ optional string blocked_src = 10;
+ optional string blocked_thread_name = 12;
+ optional bool is_blocked_thread_main = 15;
+ optional uint32 blocked_thread_tid = 21;
+
+ // Binder context
+ optional int64 binder_reply_ts = 17;
+ optional uint32 binder_reply_tid = 18;
}
message ThreadStateBreakdown {
diff --git a/protos/perfetto/metrics/android/process_metadata.proto b/protos/perfetto/metrics/android/process_metadata.proto
index fd7fe7b..fa766be 100644
--- a/protos/perfetto/metrics/android/process_metadata.proto
+++ b/protos/perfetto/metrics/android/process_metadata.proto
@@ -44,5 +44,8 @@
// https://developer.android.com/guide/topics/manifest/manifest-element#uid
repeated Package packages_for_uid = 8;
+ // Pid of the process name.
+ optional int64 pid = 9;
+
reserved 3, 4, 5, 6;
}
diff --git a/protos/perfetto/metrics/android/startup_metric.proto b/protos/perfetto/metrics/android/startup_metric.proto
index 95a2ff0..67c9044 100644
--- a/protos/perfetto/metrics/android/startup_metric.proto
+++ b/protos/perfetto/metrics/android/startup_metric.proto
@@ -47,7 +47,7 @@
// Timing information spanning the intent received by the
// activity manager to the first frame drawn.
- // Next id: 34.
+ // Next id: 35.
message ToFirstFrame {
// The duration between the intent received and first frame.
optional int64 dur_ns = 1;
@@ -121,6 +121,10 @@
// being started up.
optional Slice time_dex_open_thread_main = 33;
+ // Time spent in dlopening .so files on the main thread of the process
+ // being started up.
+ optional Slice time_dlopen_thread_main = 34;
+
// Removed: was other_process_to_activity_cpu_ratio.
reserved 12;
@@ -220,7 +224,7 @@
optional int64 dex2oat_dur_ns = 7;
}
- // Next id: 20
+ // Next id: 21
message Startup {
// Random id uniquely identifying an app startup in this trace.
optional uint32 startup_id = 1;
@@ -276,6 +280,9 @@
// Contains information about the class verification.
repeated VerifyClass verify_class = 19;
+ // Contains the dlopen file names.
+ repeated string dlopen_file = 20;
+
// Package name of startups running concurrent to the launch.
repeated string startup_concurrent_to_launch = 18;
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index 60ffcd4..393095c 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -42,6 +42,9 @@
// https://developer.android.com/guide/topics/manifest/manifest-element#uid
repeated Package packages_for_uid = 8;
+ // Pid of the process name.
+ optional int64 pid = 9;
+
reserved 3, 4, 5, 6;
}
@@ -222,6 +225,9 @@
optional uint32 client_tid = 15;
optional uint32 server_tid = 16;
+
+ optional uint32 client_pid = 17;
+ optional uint32 server_pid = 18;
}
message ThreadStateBreakdown {
@@ -1019,7 +1025,7 @@
optional int64 obj_count = 3;
}
- // Next id: 10
+ // Next id: 11
message Sample {
optional int64 ts = 1;
// Size of the Java heap in bytes
@@ -1038,6 +1044,8 @@
// ART root objects
repeated HeapRoots roots = 7;
+ // OOM adjustment score
+ optional int64 oom_score_adj = 10;
}
// Heap stats per process. One sample per dump (can be > 1 if continuous
@@ -1185,28 +1193,38 @@
// This metric provides information about the monitor contention graph in a
// trace
message AndroidMonitorContentionMetric {
+ // Next field id: 24
message Node {
+ // Global context
optional int64 node_parent_id = 1;
optional int64 node_id = 2;
optional int64 ts = 3;
optional int64 dur = 4;
- optional string blocking_method = 5;
- optional string blocked_method = 6;
- optional string short_blocking_method = 7;
- optional string short_blocked_method = 8;
- optional string blocking_src = 9;
- optional string blocked_src = 10;
- optional uint32 waiter_count = 11;
- optional string blocked_thread_name = 12;
- optional string blocking_thread_name = 13;
optional string process_name = 14;
- optional bool is_blocked_thread_main = 15;
- optional bool is_blocking_thread_main = 16;
- optional int64 binder_reply_ts = 17;
- optional uint32 binder_reply_tid = 18;
-
+ optional uint32 pid = 23;
+ optional uint32 waiter_count = 11;
repeated ThreadStateBreakdown thread_states = 19;
repeated BlockedFunctionBreakdown blocked_functions = 20;
+
+ // Blocking context
+ optional string blocking_method = 5;
+ optional string short_blocking_method = 7;
+ optional string blocking_src = 9;
+ optional string blocking_thread_name = 13;
+ optional bool is_blocking_thread_main = 16;
+ optional uint32 blocking_thread_tid = 22;
+
+ // Blocked context
+ optional string blocked_method = 6;
+ optional string short_blocked_method = 8;
+ optional string blocked_src = 10;
+ optional string blocked_thread_name = 12;
+ optional bool is_blocked_thread_main = 15;
+ optional uint32 blocked_thread_tid = 21;
+
+ // Binder context
+ optional int64 binder_reply_ts = 17;
+ optional uint32 binder_reply_tid = 18;
}
message ThreadStateBreakdown {
@@ -1591,7 +1609,7 @@
// Timing information spanning the intent received by the
// activity manager to the first frame drawn.
- // Next id: 34.
+ // Next id: 35.
message ToFirstFrame {
// The duration between the intent received and first frame.
optional int64 dur_ns = 1;
@@ -1665,6 +1683,10 @@
// being started up.
optional Slice time_dex_open_thread_main = 33;
+ // Time spent in dlopening .so files on the main thread of the process
+ // being started up.
+ optional Slice time_dlopen_thread_main = 34;
+
// Removed: was other_process_to_activity_cpu_ratio.
reserved 12;
@@ -1764,7 +1786,7 @@
optional int64 dex2oat_dur_ns = 7;
}
- // Next id: 20
+ // Next id: 21
message Startup {
// Random id uniquely identifying an app startup in this trace.
optional uint32 startup_id = 1;
@@ -1820,6 +1842,9 @@
// Contains information about the class verification.
repeated VerifyClass verify_class = 19;
+ // Contains the dlopen file names.
+ repeated string dlopen_file = 20;
+
// Package name of startups running concurrent to the launch.
repeated string startup_concurrent_to_launch = 18;
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index d208b94..e886311 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -833,6 +833,7 @@
// If > 0 samples counters (see process_stats.proto) from
// /proc/pid/status and oom_score_adj every X ms.
+ // It will also sample /proc/pid/smaps_rollup if scan_smaps_rollup = true.
// This is required to be > 100ms to avoid excessive CPU usage.
// TODO(primiano): add CPU cost for change this value.
optional uint32 proc_stats_poll_ms = 4;
@@ -861,6 +862,10 @@
// new fds opened after initially scanning a process will not be
// recognized.
optional bool resolve_process_fds = 9;
+
+ // If enabled memory stats from /proc/pid/smaps_rollup will be included
+ // in process stats.
+ optional bool scan_smaps_rollup = 10;
}
// End of protos/perfetto/config/process_stats/process_stats_config.proto
@@ -2700,7 +2705,7 @@
// It contains the general config for the logging buffer(s) and the configs for
// all the data source being enabled.
//
-// Next id: 37.
+// Next id: 38.
message TraceConfig {
message BufferConfig {
optional uint32 size_kb = 1;
@@ -2968,12 +2973,35 @@
// consumer.
STOP_TRACING = 2;
- // NOTE: do not add new enum values here because of a subtle backward
- // compat bug which might cause indefinite tracing on older versions of
- // the service. See b/274931668 .
+ // When this mode is chosen, this causes a snapshot of the current tracing
+ // session to be created after |stop_delay_ms| while the current tracing
+ // session continues undisturbed (% an extra flush). This mode can be
+ // used only when the tracing session is handled by the "perfetto" cmdline
+ // client (which is true in 90% of cases). Part of the business logic
+ // necessary for this behavior, and ensuing file handling, lives in
+ // perfetto_cmd.cc . On other consumers, this causes only a notification
+ // of the trigger through a CloneTriggerHit ObservableEvent. The custom
+ // consumer is supposed to call CloneSession() itself after the event.
+ // Use use_clone_snapshot_if_available=true when targeting older versions
+ // of perfetto.
+ CLONE_SNAPSHOT = 3;
+
+ // NOTE: CLONE_SNAPSHOT should be used only when we targeting Android U+
+ // (14+) / Perfetto v34+. A bug in older versions of the tracing service
+ // might cause indefinitely long tracing sessions (see b/274931668).
}
optional TriggerMode trigger_mode = 1;
+ // This flag is really a workaround for b/274931668. This is needed only
+ // when deploying configs to different versions of the tracing service.
+ // When this is set to true this has the same effect of setting trigger_mode
+ // to CLONE_SNAPSHOT on newer versions of the service. This boolean has been
+ // introduced to allow to have configs that use CLONE_SNAPSHOT on newer
+ // versions of Android and fall back to STOP_TRACING on older versions where
+ // CLONE_SNAPSHOT did not exist.
+ // When using this flag, trigger_mode must be set to STOP_TRACING.
+ optional bool use_clone_snapshot_if_available = 4;
+
message Trigger {
// The producer must specify this name to activate the trigger.
optional string name = 1;
@@ -2985,6 +3013,8 @@
// After a trigger is received either in START_TRACING or STOP_TRACING
// mode then the trace will end |stop_delay_ms| after triggering.
+ // In CLONE_SNAPSHOT mode, this is the delay between the trigger and the
+ // snapshot.
// If |prefer_suspend_clock_for_duration| is set, the duration will be
// based on wall-clock, counting also time in suspend.
optional uint32 stop_delay_ms = 3;
@@ -3064,6 +3094,11 @@
}
optional CompressionType compression_type = 24;
+ // Use the legacy codepath that compresses from perfetto_cmd.cc instead of
+ // using the new codepath that compresses from tracing_service_impl.cc. This
+ // will be removed in the future.
+ optional bool compress_from_cli = 37;
+
// Android-only. Not for general use. If set, saves the trace into an
// incident. This field is read by perfetto_cmd, rather than the tracing
// service. This field must be set when passing the --upload flag to
@@ -11216,6 +11251,13 @@
optional uint32 chrome_peak_resident_set_kb = 14;
repeated FDInfo fds = 15;
+
+ // These fields are set only when scan_smaps_rollup=true
+ optional uint64 smr_rss_kb = 16;
+ optional uint64 smr_pss_kb = 17;
+ optional uint64 smr_pss_anon_kb = 18;
+ optional uint64 smr_pss_file_kb = 19;
+ optional uint64 smr_pss_shmem_kb = 20;
}
repeated Process processes = 1;
@@ -11302,7 +11344,7 @@
// Deliberate empty message. See comment on StatsdAtom#atom below.
message Atom {}
-// One or more statsd atoms. Ideally this should continue to match:
+// One or more statsd atoms. This must continue to match:
// perfetto/protos/third_party/statsd/shell_data.proto
// So that we can efficiently add data from statsd directly to the
// trace.
diff --git a/protos/perfetto/trace/ps/process_stats.proto b/protos/perfetto/trace/ps/process_stats.proto
index 4ac0c40..03759b4 100644
--- a/protos/perfetto/trace/ps/process_stats.proto
+++ b/protos/perfetto/trace/ps/process_stats.proto
@@ -76,6 +76,13 @@
optional uint32 chrome_peak_resident_set_kb = 14;
repeated FDInfo fds = 15;
+
+ // These fields are set only when scan_smaps_rollup=true
+ optional uint64 smr_rss_kb = 16;
+ optional uint64 smr_pss_kb = 17;
+ optional uint64 smr_pss_anon_kb = 18;
+ optional uint64 smr_pss_file_kb = 19;
+ optional uint64 smr_pss_shmem_kb = 20;
}
repeated Process processes = 1;
diff --git a/protos/perfetto/trace/statsd/statsd_atom.proto b/protos/perfetto/trace/statsd/statsd_atom.proto
index 026766d..62ca960 100644
--- a/protos/perfetto/trace/statsd/statsd_atom.proto
+++ b/protos/perfetto/trace/statsd/statsd_atom.proto
@@ -20,7 +20,7 @@
// Deliberate empty message. See comment on StatsdAtom#atom below.
message Atom {}
-// One or more statsd atoms. Ideally this should continue to match:
+// One or more statsd atoms. This must continue to match:
// perfetto/protos/third_party/statsd/shell_data.proto
// So that we can efficiently add data from statsd directly to the
// trace.
diff --git a/protos/third_party/chromium/chrome_track_event.proto b/protos/third_party/chromium/chrome_track_event.proto
index 1f5a211..cce5e76 100644
--- a/protos/third_party/chromium/chrome_track_event.proto
+++ b/protos/third_party/chromium/chrome_track_event.proto
@@ -513,7 +513,10 @@
optional int32 browsing_instance_id = 1;
// The ID of the CoopRelatedGroup that the BrowsingContextState belongs to.
- optional int32 coop_related_group_id = 2;
+ optional int32 coop_related_group_id = 2 [deprecated = true];
+
+ // The token of the CoopRelatedGroup that the BrowsingContextState belongs to.
+ optional string coop_related_group_token = 3;
// Additional untyped debug information associated with this
// FrameTreeNode, populated via TracedProto::AddDebugAnnotations API.
diff --git a/protos/third_party/statsd/shell_data.proto b/protos/third_party/statsd/shell_data.proto
index e4c31bd..64551ea 100644
--- a/protos/third_party/statsd/shell_data.proto
+++ b/protos/third_party/statsd/shell_data.proto
@@ -20,8 +20,8 @@
// This is a manual import of ShellData:
// https://cs.android.com/android/platform/superproject/+/master:packages/modules/StatsD/statsd/src/shell/shell_data.proto;l=27;drc=d2e51ecdf08753688fb889b657dcba60adb994f3
-
+// This must exactly match perfetto.protos.StatsdAtom.
message ShellData {
repeated bytes atom = 1;
- repeated int64 timestamp_nanos = 2 [packed = true];
+ repeated int64 timestamp_nanos = 2;
}
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index ffd39d1..536dff9 100644
--- a/python/perfetto/trace_processor/metrics.descriptor
+++ b/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/android_internal/BUILD.gn b/src/android_internal/BUILD.gn
index 8435eab..a175063 100644
--- a/src/android_internal/BUILD.gn
+++ b/src/android_internal/BUILD.gn
@@ -32,6 +32,7 @@
"health_hal.cc",
"incident_service.cc",
"power_stats.cc",
+ "statsd.cc",
"statsd_logging.cc",
"tracing_service_proxy.cc",
]
@@ -53,7 +54,7 @@
"services",
"tracingproxy",
"utils",
- "libstatspull",
+ "statspull",
]
# This target should never depend on any other perfetto target to avoid ODR
diff --git a/src/android_internal/statsd.cc b/src/android_internal/statsd.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/android_internal/statsd.cc
diff --git a/src/android_stats/perfetto_atoms.h b/src/android_stats/perfetto_atoms.h
index e9ef08e..122dfad 100644
--- a/src/android_stats/perfetto_atoms.h
+++ b/src/android_stats/perfetto_atoms.h
@@ -47,6 +47,7 @@
// they log the trigger name.
kTracedTriggerStartTracing = 41,
kTracedTriggerStopTracing = 42,
+ kTracedTriggerCloneSnapshot = 53,
// Guardrails inside traced.
kTracedEnableTracingExistingTraceSession = 18,
diff --git a/src/base/http/BUILD.gn b/src/base/http/BUILD.gn
index e086134..dda19a7 100644
--- a/src/base/http/BUILD.gn
+++ b/src/base/http/BUILD.gn
@@ -40,8 +40,11 @@
"../../../gn:default_deps",
"../../../gn:gtest_and_gmock",
]
- sources = [
- "http_server_unittest.cc",
- "sha1_unittest.cc",
- ]
+ sources = [ "sha1_unittest.cc" ]
+
+ # The HTTP server unittests cannot be run in parallel. Chromium runs tests
+ # in parallel on some bots so exclude all of these ones.
+ if (!build_with_chromium) {
+ sources += [ "http_server_unittest.cc" ]
+ }
}
diff --git a/src/cloud_trace_processor/worker_impl.cc b/src/cloud_trace_processor/worker_impl.cc
index 2f124a0..6f11560 100644
--- a/src/cloud_trace_processor/worker_impl.cc
+++ b/src/cloud_trace_processor/worker_impl.cc
@@ -72,8 +72,6 @@
// pools.
auto tp = std::make_unique<TraceProcessorWrapper>(
trace, thread_pool_, TraceProcessorWrapper::Statefulness::kStateless);
- shard->tps.emplace_back(std::move(tp));
-
auto load_trace_future =
tp->LoadTrace(environment_->ReadFile(trace))
.ContinueWith(
@@ -84,6 +82,7 @@
return resp;
});
streams.emplace_back(base::StreamFromFuture(std::move(load_trace_future)));
+ shard->tps.emplace_back(std::move(tp));
}
return base::FlattenStreams(std::move(streams));
}
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 4a2b081..3052341 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -19,6 +19,7 @@
#include "perfetto/base/build_config.h"
#include "perfetto/base/proc_utils.h"
#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/ext/base/string_splitter.h"
#include <fcntl.h>
#include <stdio.h>
@@ -201,15 +202,17 @@
const char* kStateDir = "/data/misc/perfetto-traces";
PerfettoCmd::PerfettoCmd() {
- PERFETTO_DCHECK(!g_perfetto_cmd);
- g_perfetto_cmd = this;
+ // Only the main thread instance on the main thread will receive ctrl-c.
+ if (!g_perfetto_cmd)
+ g_perfetto_cmd = this;
}
PerfettoCmd::~PerfettoCmd() {
- PERFETTO_DCHECK(g_perfetto_cmd == this);
- g_perfetto_cmd = nullptr;
- if (ctrl_c_handler_installed_) {
- task_runner_.RemoveFileDescriptorWatch(ctrl_c_evt_.fd());
+ if (g_perfetto_cmd == this) {
+ g_perfetto_cmd = nullptr;
+ if (ctrl_c_handler_installed_) {
+ task_runner_.RemoveFileDescriptorWatch(ctrl_c_evt_.fd());
+ }
}
}
@@ -228,6 +231,9 @@
session, identified by its ID (see --query).
--config -c : /path/to/trace/config/file or - for stdin
--out -o : /path/to/out/trace/file or - for stdout
+ If using CLONE_SNAPSHOT triggers, each snapshot
+ will be saved in a new file with a counter suffix
+ (e.g., file.0, file.1, file.2).
--txt : Parse config as pbtxt. Not for production use.
Not a stable API.
--query : Queries the service state and prints it as
@@ -339,6 +345,7 @@
return 1;
}
+ optind = 1; // Reset getopt state. It's reused by the snapshot thread.
for (;;) {
int option =
getopt_long(argc, argv, "hc:o:dDt:b:s:a:", long_options, nullptr);
@@ -365,6 +372,14 @@
opts.categories.emplace_back("power/gpu_frequency");
PERFETTO_CHECK(CreateConfigFromOptions(opts, &test_config));
trace_config_raw = test_config.SerializeAsString();
+ } else if (strcmp(optarg, ":mem") == 0) {
+ // This is used by OnCloneSnapshotTriggerReceived(), which passes the
+ // original trace config as a member field. This is needed because, in
+ // the new PerfettoCmd instance, we need to know upfront trace config
+ // fields that affect the behaviour of perfetto_cmd, e.g., the guardrail
+ // overrides, the unique_session_name, the reporter API package etc.
+ PERFETTO_CHECK(!snapshot_config_.empty());
+ trace_config_raw = snapshot_config_;
} else {
if (!base::ReadFile(optarg, &trace_config_raw)) {
PERFETTO_PLOG("Could not open %s", optarg);
@@ -573,7 +588,7 @@
bool parsed = false;
const bool will_trace_or_trigger = !is_attach() && !query_service_;
- if (!will_trace_or_trigger || clone_tsid_) {
+ if (!will_trace_or_trigger) {
if ((!trace_config_raw.empty() || has_config_options)) {
PERFETTO_ELOG("Cannot specify a trace config with this option");
return 1;
@@ -587,7 +602,7 @@
}
parsed = CreateConfigFromOptions(config_options, trace_config_.get());
} else {
- if (trace_config_raw.empty()) {
+ if (trace_config_raw.empty() && !clone_tsid_) {
PERFETTO_ELOG("The TraceConfig is empty");
return 1;
}
@@ -784,8 +799,12 @@
packet_writer_ = CreateFilePacketWriter(trace_out_stream_.get());
}
- if (trace_config_->compression_type() ==
- TraceConfig::COMPRESSION_TYPE_DEFLATE) {
+ // TODO(b/281043457): this code path will go away after Android U. Compression
+ // has been moved to the service. This code is here only as a fallback in case
+ // of bugs in the U timeframe.
+ if (trace_config_->compress_from_cli() &&
+ trace_config_->compression_type() ==
+ TraceConfig::COMPRESSION_TYPE_DEFLATE) {
if (packet_writer_) {
#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
packet_writer_ = CreateZipPacketWriter(std::move(packet_writer_));
@@ -819,6 +838,7 @@
#endif
}
+ PERFETTO_CHECK(!snapshot_thread_); // No threads before demonization.
base::Daemonize([this]() -> int {
background_wait_pipe_.wr.reset();
@@ -992,9 +1012,16 @@
connected_ = true;
LogUploadEvent(PerfettoStatsdAtom::kOnConnect);
+ uint32_t events_mask = 0;
+ if (GetTriggerMode(*trace_config_) ==
+ TraceConfig::TriggerConfig::CLONE_SNAPSHOT) {
+ events_mask |= ObservableEvents::TYPE_CLONE_TRIGGER_HIT;
+ }
if (background_wait_) {
- consumer_endpoint_->ObserveEvents(
- perfetto::ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
+ events_mask |= ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED;
+ }
+ if (events_mask) {
+ consumer_endpoint_->ObserveEvents(events_mask);
}
if (query_service_) {
@@ -1119,6 +1146,14 @@
// be marked as "E" in the event log. Hence why LOG and not ELOG here.
PERFETTO_LOG("Service error: %s", error.c_str());
+ // In case of errors don't leave a partial file around. This happens
+ // frequently in the case of --save-for-bugreport if there is no eligible
+ // trace. See also b/279753347 .
+ if (bytes_written_ == 0 && !trace_out_path_.empty() &&
+ trace_out_path_ != "-") {
+ remove(trace_out_path_.c_str());
+ }
+
// Update guardrail state even if we failed. This is for two
// reasons:
// 1. Keeps compatibility with pre-stats code which used to
@@ -1214,6 +1249,9 @@
}
void PerfettoCmd::SetupCtrlCSignalHandler() {
+ // Only the main thread instance should handle CTRL+C.
+ if (g_perfetto_cmd != this)
+ return;
ctrl_c_handler_installed_ = true;
base::InstallCtrlCHandler([] {
if (!g_perfetto_cmd)
@@ -1282,17 +1320,18 @@
// TODO(eseckler): Support GetTraceStats().
}
-void PerfettoCmd::OnSessionCloned(bool success, const std::string& error) {
+void PerfettoCmd::OnSessionCloned(const OnSessionClonedArgs& args) {
PERFETTO_DLOG("Cloned tracing session %" PRIu64 ", success=%d",
- clone_tsid_.value_or(0), success);
+ clone_tsid_.value_or(0), args.success);
std::string full_error;
- if (!success) {
+ if (!args.success) {
full_error = "Failed to clone tracing session " +
- std::to_string(clone_tsid_.value_or(0)) + ": " + error;
+ std::to_string(clone_tsid_.value_or(0)) + ": " + args.error;
}
// Kick off the readback and file finalization (as if we started tracing and
// reached the duration_ms timeout).
+ uuid_ = args.uuid.ToString();
ReadbackTraceDataAndQuit(full_error);
}
@@ -1413,6 +1452,69 @@
if (observable_events.all_data_sources_started()) {
NotifyBgProcessPipe(kBackgroundOk);
}
+ if (observable_events.has_clone_trigger_hit()) {
+ int64_t tsid = observable_events.clone_trigger_hit().tracing_session_id();
+ OnCloneSnapshotTriggerReceived(static_cast<TracingSessionID>(tsid));
+ }
+}
+
+void PerfettoCmd::OnCloneSnapshotTriggerReceived(TracingSessionID tsid) {
+ PERFETTO_DLOG("Creating snapshot for tracing session %" PRIu64, tsid);
+
+ // Only the main thread instance should be handling snapshots.
+ // We should never end up in a state where each secondary PerfettoCmd
+ // instance handles other snapshots and creates other threads.
+ PERFETTO_CHECK(g_perfetto_cmd == this);
+
+ std::string cmdline;
+ auto add_argv = [&cmdline](const std::string& str) {
+ cmdline.append(str);
+ cmdline.append("\0", 1);
+ };
+ add_argv("perfetto");
+ add_argv("--config");
+ add_argv(":mem"); // Use the copied config from `snapshot_config_`.
+ add_argv("--clone");
+ add_argv(std::to_string(tsid));
+ if (upload_flag_) {
+ add_argv("--upload");
+ } else if (!trace_out_path_.empty()) {
+ add_argv("--out");
+ add_argv(trace_out_path_ + "." + std::to_string(snapshot_count_++));
+ } else {
+ PERFETTO_FATAL("Cannot use CLONE_SNAPSHOT with the current cmdline args");
+ }
+
+ if (!snapshot_thread_) {
+ // The destructor of the main-thread's PerfettoCmdMain will destroy and
+ // join the secondary thread that we are crating here.
+ snapshot_thread_.reset(new base::ThreadTaskRunner(
+ base::ThreadTaskRunner::CreateAndStart("snapshot")));
+ }
+
+ // We need to pass a copy of the trace config to the new PerfettoCmd instance
+ // because the trace config defines a bunch of properties that are used by the
+ // cmdline client (reporter API package, guardrails, etc).
+ std::string trace_config_copy = trace_config_->SerializeAsString();
+
+ snapshot_thread_->PostTask([tsid, cmdline, trace_config_copy] {
+ int argc = 0;
+ char* argv[32];
+ // `splitter` needs to live on the stack for the whole scope as it owns the
+ // underlying string storage (that gets std::moved) passed PerfettoCmd.
+ base::StringSplitter splitter(std::move(cmdline), '\0');
+ while (splitter.Next()) {
+ argv[argc++] = splitter.cur_token();
+ PERFETTO_CHECK(static_cast<size_t>(argc) < base::ArraySize(argv));
+ }
+ perfetto::PerfettoCmd cmd;
+ cmd.snapshot_config_ = std::move(trace_config_copy);
+ auto cmdline_res = cmd.ParseCmdlineAndMaybeDaemonize(argc, argv);
+ PERFETTO_CHECK(!cmdline_res.has_value()); // No daemonization expected.
+ int res = cmd.ConnectToServiceRunAndMaybeNotify();
+ if (res)
+ PERFETTO_ELOG("Cloning session %" PRIu64 " failed (%d)", tsid, res);
+ });
}
void PerfettoCmd::LogUploadEvent(PerfettoStatsdAtom atom) {
diff --git a/src/perfetto_cmd/perfetto_cmd.h b/src/perfetto_cmd/perfetto_cmd.h
index 9504ca5..b55cbc8 100644
--- a/src/perfetto_cmd/perfetto_cmd.h
+++ b/src/perfetto_cmd/perfetto_cmd.h
@@ -28,6 +28,7 @@
#include "perfetto/ext/base/event_fd.h"
#include "perfetto/ext/base/pipe.h"
#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/ext/base/thread_task_runner.h"
#include "perfetto/ext/base/unix_task_runner.h"
#include "perfetto/ext/base/weak_ptr.h"
#include "perfetto/ext/tracing/core/consumer.h"
@@ -67,7 +68,7 @@
void OnAttach(bool, const TraceConfig&) override;
void OnTraceStats(bool, const TraceStats&) override;
void OnObservableEvents(const ObservableEvents&) override;
- void OnSessionCloned(bool, const std::string&) override;
+ void OnSessionCloned(const OnSessionClonedArgs&) override;
void SignalCtrlC() { ctrl_c_evt_.Notify(); }
@@ -116,6 +117,8 @@
// will have no effect.
void NotifyBgProcessPipe(BgProcessStatus status);
+ void OnCloneSnapshotTriggerReceived(TracingSessionID);
+
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
static base::ScopedFile CreateUnlinkedTmpFile();
void SaveTraceIntoIncidentOrCrash();
@@ -162,6 +165,14 @@
// How long we expect to trace for or 0 if the trace is indefinite.
uint32_t expected_duration_ms_ = 0;
bool trace_data_timeout_armed_ = false;
+
+ // The aux thread that is used to invoke secondary instances of PerfettoCmd
+ // to create snapshots. This is used only when the trace config involves a
+ // CLONE_SNAPSHOT trigger.
+ std::unique_ptr<base::ThreadTaskRunner> snapshot_thread_;
+ int snapshot_count_ = 0;
+ std::string snapshot_config_;
+
base::WeakPtrFactory<PerfettoCmd> weak_factory_{this};
};
diff --git a/src/profiling/perf/perf_producer.cc b/src/profiling/perf/perf_producer.cc
index 0fb7be3..fec5b6d 100644
--- a/src/profiling/perf/perf_producer.cc
+++ b/src/profiling/perf/perf_producer.cc
@@ -16,8 +16,10 @@
#include "src/profiling/perf/perf_producer.h"
+#include <optional>
#include <random>
#include <utility>
+#include <vector>
#include <unistd.h>
@@ -26,7 +28,9 @@
#include "perfetto/base/logging.h"
#include "perfetto/base/task_runner.h"
+#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/metatrace.h"
+#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/base/weak_ptr.h"
#include "perfetto/ext/tracing/core/basic_types.h"
@@ -80,6 +84,35 @@
return static_cast<size_t>(sysconf(_SC_NPROCESSORS_CONF));
}
+std::vector<uint32_t> GetOnlineCpus() {
+ size_t cpu_count = NumberOfCpus();
+ if (cpu_count == 0) {
+ return {};
+ }
+
+ static constexpr char kOnlineValue[] = "1\n";
+ std::vector<uint32_t> online_cpus;
+ online_cpus.reserve(cpu_count);
+ for (uint32_t cpu = 0; cpu < cpu_count; ++cpu) {
+ std::string res;
+ base::StackString<1024> path("/sys/devices/system/cpu/cpu%u/online", cpu);
+ if (!base::ReadFile(path.c_str(), &res)) {
+ // Always consider CPU 0 to be online if the "online" file does not exist
+ // for it. There seem to be several assumptions in the kernel which make
+ // CPU 0 special so this is a pretty safe bet.
+ if (cpu != 0) {
+ return {};
+ }
+ res = kOnlineValue;
+ }
+ if (res != kOnlineValue) {
+ continue;
+ }
+ online_cpus.push_back(cpu);
+ }
+ return online_cpus;
+}
+
int32_t ToBuiltinClock(int32_t clockid) {
switch (clockid) {
case CLOCK_REALTIME:
@@ -394,9 +427,14 @@
return;
}
- size_t num_cpus = NumberOfCpus();
+ std::vector<uint32_t> online_cpus = GetOnlineCpus();
+ if (online_cpus.empty()) {
+ PERFETTO_ELOG("No online CPUs found.");
+ return;
+ }
+
std::vector<EventReader> per_cpu_readers;
- for (uint32_t cpu = 0; cpu < num_cpus; cpu++) {
+ for (uint32_t cpu : online_cpus) {
std::optional<EventReader> event_reader =
EventReader::ConfigureEvents(cpu, event_config.value());
if (!event_reader.has_value()) {
diff --git a/src/protozero/proto_decoder_unittest.cc b/src/protozero/proto_decoder_unittest.cc
index 0991f88..1e962d7 100644
--- a/src/protozero/proto_decoder_unittest.cc
+++ b/src/protozero/proto_decoder_unittest.cc
@@ -592,5 +592,26 @@
ASSERT_FALSE(field.valid());
}
+// Check what happens when trying to parse packed repeated field and finding a
+// mismatching wire type instead. A compliant protobuf decoder should accept it,
+// but protozero doesn't handle that. At least it shouldn't crash.
+TEST(ProtoDecoderTest, PacketRepeatedWireTypeMismatch) {
+ protozero::HeapBuffered<pbtest::PackedRepeatedFields> message;
+ // A proper packed encoding should have a length delimited wire type. Use a
+ // var int wire type instead.
+ constexpr int kFieldId = pbtest::PackedRepeatedFields::kFieldInt32FieldNumber;
+ message->AppendTinyVarInt(kFieldId, 5);
+ auto data = message.SerializeAsArray();
+
+ pbtest::PackedRepeatedFields::Decoder decoder(data.data(), data.size());
+ bool parse_error = false;
+ auto it = decoder.field_int32(&parse_error);
+ // The decoder doesn't return a parse error (maybe it should, but that has
+ // been the behavior since the beginning).
+ ASSERT_FALSE(parse_error);
+ // But the iterator returns 0 elements.
+ EXPECT_FALSE(it);
+}
+
} // namespace
} // namespace protozero
diff --git a/src/shared_lib/test/BUILD.gn b/src/shared_lib/test/BUILD.gn
index 220439a..aa87956 100644
--- a/src/shared_lib/test/BUILD.gn
+++ b/src/shared_lib/test/BUILD.gn
@@ -22,7 +22,11 @@
"../../../gn:gtest_and_gmock",
"../../../include/perfetto/public",
]
- sources = [ "utils.cc" ]
+ sources = [
+ "utils.cc",
+ "utils.h",
+ ]
+ defines = [ "PERFETTO_SDK_DISABLE_SHLIB_EXPORT" ]
}
if (enable_perfetto_benchmarks) {
@@ -35,6 +39,7 @@
"../../../gn:default_deps",
"../../../include/perfetto/public",
]
+ defines = [ "PERFETTO_SDK_DISABLE_SHLIB_EXPORT" ]
sources = [ "benchmark.cc" ]
}
}
@@ -49,6 +54,7 @@
"../../../gn:gtest_and_gmock",
"../../../include/perfetto/public",
]
+ defines = [ "PERFETTO_SDK_DISABLE_SHLIB_EXPORT" ]
sources = [ "api_integrationtest.cc" ]
}
}
diff --git a/src/tools/ftrace_proto_gen/ftrace_proto_gen.cc b/src/tools/ftrace_proto_gen/ftrace_proto_gen.cc
index f692373..712e3d1 100644
--- a/src/tools/ftrace_proto_gen/ftrace_proto_gen.cc
+++ b/src/tools/ftrace_proto_gen/ftrace_proto_gen.cc
@@ -191,6 +191,11 @@
// configurations)
if (group == "ftrace" && proto.event_name == "print" && field->name == "ip")
continue;
+ // Ignore the "nid" field. On new kernels, this field has a type that we
+ // don't know how to parse. See b/281660544
+ if (group == "f2fs" && proto.event_name == "f2fs_truncate_partial_nodes" &&
+ field->name == "nid")
+ continue;
s += "{";
s += "kUnsetOffset, ";
s += "kUnsetSize, ";
diff --git a/src/trace_processor/containers/bit_vector.h b/src/trace_processor/containers/bit_vector.h
index c1cdc33..a9a5fbd 100644
--- a/src/trace_processor/containers/bit_vector.h
+++ b/src/trace_processor/containers/bit_vector.h
@@ -89,17 +89,10 @@
std::vector<uint32_t> counts(no_blocks);
// Calculate counts only for full blocks.
- for (uint32_t i = 1; i < no_blocks - 1; ++i) {
- counts[i] +=
- counts[i - 1] +
- ConstBlock(&words_[Block::kWords * (i - 1)]).CountSetBits();
+ for (uint32_t i = 1; i < no_blocks; ++i) {
+ counts[i] = counts[i - 1] +
+ ConstBlock(&words_[Block::kWords * (i - 1)]).CountSetBits();
}
- if (size_ % Block::kBits == 0) {
- counts[no_blocks - 1] +=
- counts[no_blocks - 2] +
- ConstBlock(&words_[Block::kWords * (no_blocks - 2)]).CountSetBits();
- }
-
return BitVector{std::move(words_), std::move(counts), size_};
}
diff --git a/src/trace_processor/containers/bit_vector_unittest.cc b/src/trace_processor/containers/bit_vector_unittest.cc
index 3db984c..dd8c951 100644
--- a/src/trace_processor/containers/bit_vector_unittest.cc
+++ b/src/trace_processor/containers/bit_vector_unittest.cc
@@ -572,6 +572,22 @@
ASSERT_FALSE(bv.IsSet(2));
}
+TEST(BitVectorUnittest, BuilderCountSetBits) {
+ // 16 words and 1 bit
+ BitVector::Builder builder(1025);
+
+ // 100100011010001010110011110001001 as a hex literal, with 15 set bits.
+ uint64_t word = 0x123456789;
+ for (uint32_t i = 0; i < 16; ++i) {
+ builder.AppendWord(word);
+ }
+ builder.Append(1);
+ BitVector bv = std::move(builder).Build();
+
+ ASSERT_EQ(bv.CountSetBits(500), 120u);
+ ASSERT_EQ(bv.CountSetBits(), 16 * 15 + 1u);
+}
+
TEST(BitVectorUnittest, BuilderStressTest) {
// Space for 128 words and 1 bit
uint32_t size = 8 * 1024 + 1;
@@ -590,7 +606,7 @@
ASSERT_EQ(builder.BitsUntilFull(), size - 1024);
ASSERT_EQ(builder.BitsUntilWordBoundaryOrFull(), 0u);
- // 100100011010001010110011110001001 as a hex literal.
+ // 100100011010001010110011110001001 as a hex literal, with 15 set bits.
uint64_t word = 0x123456789;
// Add all of the remaining words.
@@ -607,6 +623,8 @@
builder.Append(1);
BitVector bv = std::move(builder).Build();
+
+ ASSERT_EQ(bv.CountSetBits(), 2681u);
ASSERT_EQ(bv.size(), 8u * 1024u + 1u);
ASSERT_TRUE(bv.IsSet(0));
diff --git a/src/trace_processor/db/BUILD.gn b/src/trace_processor/db/BUILD.gn
index bcde78f..043b2af 100644
--- a/src/trace_processor/db/BUILD.gn
+++ b/src/trace_processor/db/BUILD.gn
@@ -20,17 +20,20 @@
"base_id.h",
"column.cc",
"column.h",
+ "column_overlay.cc",
"column_overlay.h",
"column_storage.cc",
"column_storage.h",
"column_storage_overlay.h",
"compare.h",
+ "null_overlay.cc",
"null_overlay.h",
"numeric_storage.cc",
"numeric_storage.h",
"sorting_overlay.h",
"storage.cc",
"storage.h",
+ "storage_overlay.cc",
"storage_overlay.h",
"storage_variants.h",
"table.cc",
diff --git a/src/trace_processor/prelude/functions/register_function.cc b/src/trace_processor/db/column_overlay.cc
similarity index 67%
copy from src/trace_processor/prelude/functions/register_function.cc
copy to src/trace_processor/db/column_overlay.cc
index ef41f1d..599a3b2 100644
--- a/src/trace_processor/prelude/functions/register_function.cc
+++ b/src/trace_processor/db/column_overlay.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open 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,18 +14,14 @@
* limitations under the License.
*/
-#include "src/trace_processor/prelude/functions/register_function.h"
-#include "sqlite3.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/db/column_overlay.h"
namespace perfetto {
namespace trace_processor {
+namespace column {
-base::Status SqlFunction::VerifyPostConditions(Context*) {
- return base::OkStatus();
-}
+ColumnOverlay::~ColumnOverlay() = default;
-void SqlFunction::Cleanup(Context*) {}
-
+} // namespace column
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/db/column_overlay.h b/src/trace_processor/db/column_overlay.h
index 7dc15f9..e3bad53 100644
--- a/src/trace_processor/db/column_overlay.h
+++ b/src/trace_processor/db/column_overlay.h
@@ -37,10 +37,10 @@
// Clears the rows of RowMap, on which data don't match the FilterOp operation
// with SqlValue. Efficient.
- virtual void Filter(FilterOp, SqlValue, RowMap&) = 0;
+ virtual void Filter(FilterOp, SqlValue, RowMap&) const = 0;
// Sorts (ascending) provided vector of indices based on storage.
- virtual void Sort(std::vector<uint32_t>&) = 0;
+ virtual void StableSort(uint32_t* rows, uint32_t rows_size) const = 0;
};
} // namespace column
} // namespace trace_processor
diff --git a/src/trace_processor/db/null_overlay.cc b/src/trace_processor/db/null_overlay.cc
new file mode 100644
index 0000000..ade46c5
--- /dev/null
+++ b/src/trace_processor/db/null_overlay.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/db/null_overlay.h"
+
+#include "src/trace_processor/db/storage_variants.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace column {
+
+void NullOverlay::Filter(FilterOp op, SqlValue sql_val, RowMap& rm) const {
+ if (op == FilterOp::kIsNull) {
+ rm.Intersect(RowMap(null_bv_->Not()));
+ return;
+ }
+ if (op == FilterOp::kIsNotNull) {
+ rm.Intersect(RowMap(null_bv_->Copy()));
+ return;
+ }
+
+ // Row map for filtered data, not the size of whole column.
+ RowMap filtered_data_rm(0, null_bv_->CountSetBits());
+ inner_->Filter(op, sql_val, filtered_data_rm);
+
+ // Select only rows that were not filtered out from null BitVector and
+ // intersect it with RowMap&.
+ rm.Intersect(RowMap(null_bv_->Copy()).SelectRows(filtered_data_rm));
+}
+
+void NullOverlay::StableSort(uint32_t* rows, uint32_t rows_size) const {
+ uint32_t count_set_bits = null_bv_->CountSetBits();
+
+ std::vector<uint32_t> non_null_rows(count_set_bits);
+ std::vector<uint32_t> storage_to_rows(count_set_bits);
+
+ // Saving the map from `out` index to `storage` index gives us free `IsSet()`
+ // function, which would be very expensive otherwise.
+ for (auto it = null_bv_->IterateSetBits(); it; it.Next()) {
+ storage_to_rows[it.ordinal()] = it.index();
+ }
+
+ uint32_t cur_non_null_id = 0;
+ uint32_t cur_null_id = 0;
+
+ // Sort elements into null and non null.
+ for (uint32_t i = 0; i < rows_size; ++i) {
+ uint32_t row_idx = rows[i];
+ auto it = std::lower_bound(storage_to_rows.begin(), storage_to_rows.end(),
+ row_idx);
+
+ // This condition holds if the row is null.
+ if (it == storage_to_rows.end() || *it != row_idx) {
+ // We can override the out because we already used this data.
+ rows[cur_null_id++] = row_idx;
+ continue;
+ }
+
+ uint32_t non_null_idx =
+ static_cast<uint32_t>(std::distance(storage_to_rows.begin(), it));
+ non_null_rows[cur_non_null_id++] = non_null_idx;
+ }
+
+ // Sort storage and translate them into `rows` indices.
+ inner_->StableSort(non_null_rows.data(), count_set_bits);
+ uint32_t set_rows_offset = null_bv_->size() - count_set_bits;
+ for (uint32_t i = 0; i < count_set_bits; ++i) {
+ rows[set_rows_offset + i] = storage_to_rows[non_null_rows[i]];
+ }
+}
+
+} // namespace column
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/db/null_overlay.h b/src/trace_processor/db/null_overlay.h
index 52cf85c..43d2fed 100644
--- a/src/trace_processor/db/null_overlay.h
+++ b/src/trace_processor/db/null_overlay.h
@@ -30,9 +30,12 @@
// Overlay responsible for operations related to column nullability.
class NullOverlay : public ColumnOverlay {
public:
- explicit NullOverlay(std::unique_ptr<ColumnOverlay>);
- void Filter(FilterOp, SqlValue, RowMap&) override;
- void Sort(std::vector<uint32_t>&) override;
+ explicit NullOverlay(std::unique_ptr<ColumnOverlay> inner,
+ const BitVector* null_bv)
+ : inner_(std::move(inner)), null_bv_(null_bv) {}
+
+ void Filter(FilterOp, SqlValue, RowMap&) const override;
+ void StableSort(uint32_t* rows, uint32_t rows_size) const override;
private:
std::unique_ptr<ColumnOverlay> inner_;
diff --git a/src/trace_processor/db/numeric_storage.cc b/src/trace_processor/db/numeric_storage.cc
index a1984a8..3b66e22 100644
--- a/src/trace_processor/db/numeric_storage.cc
+++ b/src/trace_processor/db/numeric_storage.cc
@@ -26,37 +26,6 @@
namespace column {
namespace {
-// As we don't template those functions, we need to use std::visitor to type
-// `start`, hence this wrapping.
-inline uint32_t UpperBoundIndex(NumericValue val,
- const void* start,
- uint32_t num_elements) {
- return std::visit(
- [start, num_elements](auto val_data) {
- using T = decltype(val_data);
- const T* typed_start = static_cast<const T*>(start);
- auto upper =
- std::upper_bound(typed_start, typed_start + num_elements, val_data);
- return static_cast<uint32_t>(std::distance(typed_start, upper));
- },
- val);
-}
-
-// As we don't template those functions, we need to use std::visitor to type
-// `start`, hence this wrapping.
-inline uint32_t LowerBoundIndex(NumericValue val,
- const void* start,
- uint32_t num_elements) {
- return std::visit(
- [start, num_elements](auto val_data) {
- using T = decltype(val_data);
- const T* typed_start = static_cast<const T*>(start);
- auto upper =
- std::lower_bound(typed_start, typed_start + num_elements, val_data);
- return static_cast<uint32_t>(std::distance(typed_start, upper));
- },
- val);
-}
// Templated part of FastPathComparison.
template <typename T>
@@ -108,13 +77,13 @@
} // namespace
-void NumericStorage::StableSort(std::vector<uint32_t>& out) const {
+void NumericStorage::StableSort(uint32_t* rows, uint32_t rows_size) const {
NumericValue val = *GetNumericTypeVariant(type_, SqlValue::Long(0));
std::visit(
- [this, &out](auto val_data) {
+ [this, &rows, rows_size](auto val_data) {
using T = decltype(val_data);
const T* typed_start = static_cast<const T*>(data_);
- std::stable_sort(out.begin(), out.end(),
+ std::stable_sort(rows, rows + rows_size,
[typed_start](uint32_t a_idx, uint32_t b_idx) {
T first_val = typed_start[a_idx];
T second_val = typed_start[b_idx];
@@ -127,9 +96,10 @@
// Responsible for invoking templated version of FastPathComparison.
void NumericStorage::CompareFast(FilterOp op,
SqlValue sql_val,
- const void* start,
+ uint32_t offset,
uint32_t num_elements,
BitVector::Builder& builder) const {
+ PERFETTO_DCHECK(num_elements % BitVector::kBitsInWord == 0);
std::optional<NumericValue> val = GetNumericTypeVariant(type_, sql_val);
// If the value is invalid we should just ignore those elements.
@@ -139,9 +109,9 @@
return;
}
std::visit(
- [op, start, num_elements, &builder](auto num_val) {
+ [this, op, offset, num_elements, &builder](auto num_val) {
using T = decltype(num_val);
- auto* typed_start = static_cast<const T*>(start);
+ auto* typed_start = static_cast<const T*>(data_) + offset;
TypedFastPathComparison(num_val, op, typed_start, num_elements,
builder);
},
@@ -151,7 +121,7 @@
// Responsible for invoking templated version of SlowPathComparison.
void NumericStorage::CompareSlow(FilterOp op,
SqlValue sql_val,
- const void* start,
+ uint32_t offset,
uint32_t num_elements,
BitVector::Builder& builder) const {
std::optional<NumericValue> val = GetNumericTypeVariant(type_, sql_val);
@@ -164,18 +134,42 @@
}
std::visit(
- [op, start, num_elements, &builder](auto val) {
+ [this, op, offset, num_elements, &builder](auto val) {
using T = decltype(val);
- auto* typed_start = static_cast<const T*>(start);
+ auto* typed_start = static_cast<const T*>(data_) + offset;
TypedSlowPathComparison(val, op, typed_start, num_elements, builder);
},
*val);
}
+uint32_t NumericStorage::UpperBoundIndex(NumericValue val) const {
+ return std::visit(
+ [this](auto val_data) {
+ using T = decltype(val_data);
+ const T* typed_start = static_cast<const T*>(data_);
+ auto upper =
+ std::upper_bound(typed_start, typed_start + size_, val_data);
+ return static_cast<uint32_t>(std::distance(typed_start, upper));
+ },
+ val);
+}
+
+// As we don't template those functions, we need to use std::visitor to type
+// `start`, hence this wrapping.
+uint32_t NumericStorage::LowerBoundIndex(NumericValue val) const {
+ return std::visit(
+ [this](auto val_data) {
+ using T = decltype(val_data);
+ const T* typed_start = static_cast<const T*>(data_);
+ auto lower =
+ std::lower_bound(typed_start, typed_start + size_, val_data);
+ return static_cast<uint32_t>(std::distance(typed_start, lower));
+ },
+ val);
+}
+
void NumericStorage::CompareSorted(FilterOp op,
SqlValue sql_val,
- const void* start,
- uint32_t num_elements,
RowMap& rm) const {
std::optional<NumericValue> val = GetNumericTypeVariant(type_, sql_val);
if (!val.has_value() || op == FilterOp::kIsNotNull ||
@@ -186,33 +180,33 @@
switch (op) {
case FilterOp::kEq: {
- uint32_t beg = LowerBoundIndex(*val, start, num_elements);
- uint32_t end = UpperBoundIndex(*val, start, num_elements);
+ uint32_t beg = LowerBoundIndex(*val);
+ uint32_t end = UpperBoundIndex(*val);
RowMap sec(beg, end);
rm.Intersect(sec);
return;
}
case FilterOp::kLe: {
- uint32_t end = UpperBoundIndex(*val, start, num_elements);
+ uint32_t end = UpperBoundIndex(*val);
RowMap sec(0, end);
rm.Intersect(sec);
return;
}
case FilterOp::kLt: {
- uint32_t end = LowerBoundIndex(*val, start, num_elements);
+ uint32_t end = LowerBoundIndex(*val);
RowMap sec(0, end);
rm.Intersect(sec);
return;
}
case FilterOp::kGe: {
- uint32_t beg = LowerBoundIndex(*val, start, num_elements);
- RowMap sec(beg, num_elements);
+ uint32_t beg = LowerBoundIndex(*val);
+ RowMap sec(beg, size_);
rm.Intersect(sec);
return;
}
case FilterOp::kGt: {
- uint32_t beg = UpperBoundIndex(*val, start, num_elements);
- RowMap sec(beg, num_elements);
+ uint32_t beg = UpperBoundIndex(*val);
+ RowMap sec(beg, size_);
rm.Intersect(sec);
return;
}
@@ -225,6 +219,90 @@
return;
}
+uint32_t NumericStorage::UpperBoundIndex(NumericValue val,
+ uint32_t* order) const {
+ return std::visit(
+ [this, order](auto val_data) {
+ using T = decltype(val_data);
+ const T* typed_start = static_cast<const T*>(data_);
+ auto upper = std::upper_bound(order, order + size_, val_data,
+ [typed_start](T val, uint32_t index) {
+ return val < *(typed_start + index);
+ });
+ return static_cast<uint32_t>(std::distance(order, upper));
+ },
+ val);
+}
+
+// As we don't template those functions, we need to use std::visitor to type
+// `start`, hence this wrapping.
+uint32_t NumericStorage::LowerBoundIndex(NumericValue val,
+ uint32_t* order) const {
+ return std::visit(
+ [this, order](auto val_data) {
+ using T = decltype(val_data);
+ const T* typed_start = static_cast<const T*>(data_);
+ auto lower = std::lower_bound(order, order + size_, val_data,
+ [typed_start](uint32_t index, T val) {
+ return *(typed_start + index) < val;
+ });
+ return static_cast<uint32_t>(std::distance(order, lower));
+ },
+ val);
+}
+
+void NumericStorage::CompareSortedIndexes(FilterOp op,
+ SqlValue sql_val,
+ uint32_t* order,
+ RowMap& rm) const {
+ std::optional<NumericValue> val = GetNumericTypeVariant(type_, sql_val);
+ if (!val.has_value() || op == FilterOp::kIsNotNull ||
+ op == FilterOp::kIsNull || op == FilterOp::kGlob) {
+ rm.Clear();
+ return;
+ }
+
+ switch (op) {
+ case FilterOp::kEq: {
+ uint32_t beg = LowerBoundIndex(*val, order);
+ uint32_t end = UpperBoundIndex(*val, order);
+ std::vector<uint32_t> index(order + beg, order + end);
+ rm.Intersect(RowMap(std::move(index)));
+ return;
+ }
+ case FilterOp::kLe: {
+ uint32_t end = UpperBoundIndex(*val, order);
+ std::vector<uint32_t> index(order, order + end);
+ rm.Intersect(RowMap(std::move(index)));
+ return;
+ }
+ case FilterOp::kLt: {
+ uint32_t end = LowerBoundIndex(*val, order);
+ std::vector<uint32_t> index(order, order + end);
+ rm.Intersect(RowMap(std::move(index)));
+ return;
+ }
+ case FilterOp::kGe: {
+ uint32_t beg = LowerBoundIndex(*val, order);
+ std::vector<uint32_t> index(order + beg, order + size_);
+ rm.Intersect(RowMap(std::move(index)));
+ return;
+ }
+ case FilterOp::kGt: {
+ uint32_t beg = UpperBoundIndex(*val, order);
+ std::vector<uint32_t> index(order + beg, order + size_);
+ rm.Intersect(RowMap(std::move(index)));
+ return;
+ }
+ case FilterOp::kNe:
+ case FilterOp::kIsNull:
+ case FilterOp::kIsNotNull:
+ case FilterOp::kGlob:
+ rm.Clear();
+ }
+ return;
+}
+
} // namespace column
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/db/numeric_storage.h b/src/trace_processor/db/numeric_storage.h
index 7677f82..a85044b 100644
--- a/src/trace_processor/db/numeric_storage.h
+++ b/src/trace_processor/db/numeric_storage.h
@@ -28,37 +28,52 @@
class NumericStorage : public Storage {
public:
- NumericStorage(const void* data, ColumnType type)
- : type_(type), data_(data) {}
+ NumericStorage(void* data, uint32_t size, ColumnType type)
+ : type_(type), data_(data), size_(size) {}
- void StableSort(std::vector<uint32_t>&) const override;
+ void StableSort(uint32_t* rows, uint32_t rows_size) const override;
void CompareFast(FilterOp op,
SqlValue val,
- const void* start,
+ uint32_t offset,
uint32_t num_elements,
BitVector::Builder& builder) const override;
- // Inefficiently compares series of |num_elements| of data from |data_start|
- // to comparator value and appends results to BitVector::Builder. Should be
- // avoided if possible, with `FastSeriesComparison` used instead.
void CompareSlow(FilterOp op,
SqlValue val,
- const void* start,
+ uint32_t offset,
uint32_t num_elements,
BitVector::Builder& builder) const override;
- // Compares sorted (asc) series of |num_elements| of data from |data_start| to
- // comparator value. Should be used where possible.
- void CompareSorted(FilterOp op,
- SqlValue val,
- const void* data_start,
- uint32_t num_elements,
- RowMap&) const override;
+ void CompareSorted(FilterOp op, SqlValue val, RowMap&) const override;
+
+ void CompareSortedIndexes(FilterOp op,
+ SqlValue val,
+ uint32_t* order,
+ RowMap&) const override;
+
+ uint32_t size() const override { return size_; }
private:
+ // As we don't template those functions, we need to use std::visitor to type
+ // `start`, hence this wrapping.
+ uint32_t UpperBoundIndex(NumericValue val) const;
+
+ // As we don't template those functions, we need to use std::visitor to type
+ // `start`, hence this wrapping.
+ uint32_t LowerBoundIndex(NumericValue val) const;
+
+ // As we don't template those functions, we need to use std::visitor to type
+ // `start`, hence this wrapping.
+ uint32_t UpperBoundIndex(NumericValue val, uint32_t* order) const;
+
+ // As we don't template those functions, we need to use std::visitor to type
+ // `start`, hence this wrapping.
+ uint32_t LowerBoundIndex(NumericValue val, uint32_t* order) const;
+
const ColumnType type_;
const void* data_;
+ const uint32_t size_;
};
} // namespace column
diff --git a/src/trace_processor/db/sorting_overlay.h b/src/trace_processor/db/sorting_overlay.h
index 86a5676..7b536a1 100644
--- a/src/trace_processor/db/sorting_overlay.h
+++ b/src/trace_processor/db/sorting_overlay.h
@@ -31,8 +31,8 @@
class SortingOverlay : public ColumnOverlay {
public:
explicit SortingOverlay(ColumnOverlay* ancestor);
- void Filter(FilterOp, SqlValue, RowMap&) override;
- void Sort(std::vector<uint32_t>&) override;
+ void Filter(FilterOp, SqlValue, RowMap&) const override;
+ void StableSort(uint32_t* rows_order, uint32_t rows_size) const override;
private:
std::unique_ptr<ColumnOverlay> inner_;
diff --git a/src/trace_processor/db/storage.h b/src/trace_processor/db/storage.h
index dbf037d..41e616f 100644
--- a/src/trace_processor/db/storage.h
+++ b/src/trace_processor/db/storage.h
@@ -31,14 +31,14 @@
virtual ~Storage();
// Changes the vector of indices to represent the sorted state of the column.
- virtual void StableSort(std::vector<uint32_t>&) const = 0;
+ virtual void StableSort(uint32_t* rows, uint32_t rows_size) const = 0;
// Efficiently compares series of |num_elements| of data from |data_start| to
// comparator value and appends results to BitVector::Builder. Should be used
// on as much data as possible.
virtual void CompareFast(FilterOp op,
SqlValue value,
- const void* start,
+ uint32_t offset,
uint32_t compare_elements_count,
BitVector::Builder&) const = 0;
@@ -47,17 +47,23 @@
// avoided if possible, with `FastSeriesComparison` used instead.
virtual void CompareSlow(FilterOp op,
SqlValue value,
- const void* data_start,
+ uint32_t offset,
uint32_t compare_elements_count,
BitVector::Builder&) const = 0;
- // Compares sorted (asc) series of |num_elements| of data from |data_start| to
- // comparator value. Should be used where possible.
- virtual void CompareSorted(FilterOp op,
- SqlValue value,
- const void* data_start,
- uint32_t compare_elements_count,
- RowMap&) const = 0;
+ // Compares sorted (asc) series data with comparator value. Should be used
+ // where possible.
+ virtual void CompareSorted(FilterOp op, SqlValue value, RowMap&) const = 0;
+
+ // Compares sorted (asc) with `order` vector series with comparator value.
+ // Should be used where possible.
+ virtual void CompareSortedIndexes(FilterOp op,
+ SqlValue value,
+ uint32_t* order,
+ RowMap&) const = 0;
+
+ // Number of elements in stored data.
+ virtual uint32_t size() const = 0;
};
} // namespace column
diff --git a/src/trace_processor/db/storage_overlay.cc b/src/trace_processor/db/storage_overlay.cc
new file mode 100644
index 0000000..2ab4fde
--- /dev/null
+++ b/src/trace_processor/db/storage_overlay.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/db/storage_overlay.h"
+
+#include "src/trace_processor/db/storage_variants.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace column {
+
+void StorageOverlay::Filter(FilterOp op, SqlValue value, RowMap& rm) const {
+ if (op == FilterOp::kIsNotNull)
+ return;
+
+ if (op == FilterOp::kIsNull) {
+ rm.Clear();
+ return;
+ }
+
+ BitVector::Builder builder(storage_->size());
+ // Slow path: we compare <64 elements and append to get us to a word
+ // boundary.
+ uint32_t front_elements = builder.BitsUntilWordBoundaryOrFull();
+ storage_->CompareSlow(op, value, 0, front_elements, builder);
+ uint32_t cur_index = front_elements;
+
+ // Fast path: we compare as many groups of 64 elements as we can.
+ // This should be very easy for the compiler to auto-vectorize.
+ uint32_t fast_path_elements = builder.BitsInCompleteWordsUntilFull();
+ storage_->CompareFast(op, value, cur_index, fast_path_elements, builder);
+ cur_index += fast_path_elements;
+
+ // Slow path: we compare <64 elements and append to fill the Builder.
+ uint32_t back_elements = builder.BitsUntilFull();
+ storage_->CompareSlow(op, value, cur_index, back_elements, builder);
+
+ BitVector bv = std::move(builder).Build();
+ rm.Intersect(RowMap(std::move(bv)));
+}
+
+void StorageOverlay::StableSort(uint32_t* rows, uint32_t rows_size) const {
+ storage_->StableSort(rows, rows_size);
+}
+
+} // namespace column
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/db/storage_overlay.h b/src/trace_processor/db/storage_overlay.h
index 2690919..9b0b5ec 100644
--- a/src/trace_processor/db/storage_overlay.h
+++ b/src/trace_processor/db/storage_overlay.h
@@ -30,9 +30,9 @@
// Overlay responsible for doing operations on storage.
class StorageOverlay : public ColumnOverlay {
public:
- explicit StorageOverlay(const Storage*);
- void Filter(FilterOp, SqlValue, RowMap&) override;
- void Sort(std::vector<uint32_t>&) override;
+ explicit StorageOverlay(const Storage* storage) : storage_(storage) {}
+ void Filter(FilterOp, SqlValue, RowMap&) const override;
+ void StableSort(uint32_t* rows, uint32_t rows_size) const override;
private:
const Storage* storage_;
diff --git a/src/trace_processor/db/storage_unittest.cc b/src/trace_processor/db/storage_unittest.cc
index 3b8f7c4..8988c00 100644
--- a/src/trace_processor/db/storage_unittest.cc
+++ b/src/trace_processor/db/storage_unittest.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open 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,11 @@
* limitations under the License.
*/
+#include <numeric>
#include "src/trace_processor/db/numeric_storage.h"
+#include "src/trace_processor/db/null_overlay.h"
+#include "src/trace_processor/db/storage_overlay.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
@@ -24,71 +27,267 @@
namespace {
-TEST(StorageUnittest, StableSortTrivial) {
+TEST(NumericStorageUnittest, StableSortTrivial) {
std::vector<uint32_t> data_vec{0, 1, 2, 0, 1, 2, 0, 1, 2};
std::vector<uint32_t> out = {0, 1, 2, 3, 4, 5, 6, 7, 8};
- NumericStorage storage(data_vec.data(), ColumnType::kUint32);
+ NumericStorage storage(data_vec.data(), 9, ColumnType::kUint32);
RowMap rm(0, 9);
- storage.StableSort(out);
+ storage.StableSort(out.data(), 9);
std::vector<uint32_t> stable_out{0, 3, 6, 1, 4, 7, 2, 5, 8};
ASSERT_EQ(out, stable_out);
}
-TEST(StorageUnittest, StableSort) {
+TEST(NumericStorageUnittest, StableSort) {
std::vector<uint32_t> data_vec{0, 1, 2, 0, 1, 2, 0, 1, 2};
std::vector<uint32_t> out = {1, 7, 4, 0, 6, 3, 2, 5, 8};
- NumericStorage storage(data_vec.data(), ColumnType::kUint32);
+ NumericStorage storage(data_vec.data(), 9, ColumnType::kUint32);
RowMap rm(0, 9);
- storage.StableSort(out);
+ storage.StableSort(out.data(), 9);
std::vector<uint32_t> stable_out{0, 6, 3, 1, 7, 4, 2, 5, 8};
ASSERT_EQ(out, stable_out);
}
-TEST(StorageUnittest, CompareSlow) {
- std::vector<uint32_t> data_vec{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
- NumericStorage storage(data_vec.data(), ColumnType::kUint32);
- BitVector::Builder builder(10);
- storage.CompareSlow(FilterOp::kGe, SqlValue::Long(5), data_vec.data(), 10,
- builder);
+TEST(NumericStorageUnittest, CompareSlow) {
+ uint32_t size = 10;
+ std::vector<uint32_t> data_vec(size);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ NumericStorage storage(data_vec.data(), size, ColumnType::kUint32);
+ BitVector::Builder builder(size);
+ storage.CompareSlow(FilterOp::kGe, SqlValue::Long(5), 0, size, builder);
BitVector bv = std::move(builder).Build();
ASSERT_EQ(bv.CountSetBits(), 5u);
ASSERT_EQ(bv.IndexOfNthSet(0), 5u);
}
-TEST(StorageUnittest, CompareFast) {
- std::vector<uint32_t> data_vec;
- for (uint32_t i = 0; i < 128; ++i) {
- data_vec.push_back(i);
- }
- NumericStorage storage(data_vec.data(), ColumnType::kUint32);
+TEST(NumericStorageUnittest, CompareSlowLarge) {
+ uint32_t size = 1025;
+ std::vector<uint32_t> data_vec(size);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ NumericStorage storage(data_vec.data(), size, ColumnType::kUint32);
+ BitVector::Builder builder(size);
+ storage.CompareSlow(FilterOp::kGe, SqlValue::Long(5), 0, size, builder);
+ BitVector bv = std::move(builder).Build();
+
+ ASSERT_EQ(bv.CountSetBits(), 1020u);
+ ASSERT_EQ(bv.IndexOfNthSet(0), 5u);
+}
+
+TEST(NumericStorageUnittest, CompareFast) {
+ std::vector<uint32_t> data_vec(128);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ NumericStorage storage(data_vec.data(), 128, ColumnType::kUint32);
BitVector::Builder builder(128);
- storage.CompareFast(FilterOp::kGe, SqlValue::Long(100), data_vec.data(), 128,
- builder);
+ storage.CompareFast(FilterOp::kGe, SqlValue::Long(100), 0, 128, builder);
BitVector bv = std::move(builder).Build();
ASSERT_EQ(bv.CountSetBits(), 28u);
ASSERT_EQ(bv.IndexOfNthSet(0), 100u);
}
-TEST(StorageUnittest, CompareSorted) {
- std::vector<uint32_t> data_vec;
- for (uint32_t i = 0; i < 128; ++i) {
- data_vec.push_back(i);
- }
- NumericStorage storage(data_vec.data(), ColumnType::kUint32);
+TEST(NumericStorageUnittest, CompareSorted) {
+ std::vector<uint32_t> data_vec(128);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ NumericStorage storage(data_vec.data(), 128, ColumnType::kUint32);
RowMap rm(0, 128);
- storage.CompareSorted(FilterOp::kGe, SqlValue::Long(100), data_vec.data(),
- 128, rm);
+ storage.CompareSorted(FilterOp::kGe, SqlValue::Long(100), rm);
ASSERT_EQ(rm.size(), 28u);
ASSERT_EQ(rm.Get(0), 100u);
}
+TEST(NumericStorageUnittest, CompareSortedIndexesGreaterEqual) {
+ std::vector<uint32_t> data_vec{30, 40, 50, 60, 90, 80, 70, 0, 10, 20};
+ std::vector<uint32_t> sorted_order{7, 8, 9, 0, 1, 2, 3, 6, 5, 4};
+
+ NumericStorage storage(data_vec.data(), 10, ColumnType::kUint32);
+ RowMap rm(0, 10);
+
+ storage.CompareSortedIndexes(FilterOp::kGe, SqlValue::Long(60),
+ sorted_order.data(), rm);
+
+ ASSERT_EQ(rm.size(), 4u);
+ ASSERT_EQ(rm.Get(0), 3u);
+ ASSERT_EQ(rm.Get(1), 6u);
+ ASSERT_EQ(rm.Get(2), 5u);
+ ASSERT_EQ(rm.Get(3), 4u);
+}
+
+TEST(NumericStorageUnittest, CompareSortedIndexesLess) {
+ std::vector<uint32_t> data_vec{30, 40, 50, 60, 90, 80, 70, 0, 10, 20};
+ std::vector<uint32_t> sorted_order{7, 8, 9, 0, 1, 2, 3, 6, 5, 4};
+
+ NumericStorage storage(data_vec.data(), 10, ColumnType::kUint32);
+ RowMap rm(0, 10);
+
+ storage.CompareSortedIndexes(FilterOp::kLt, SqlValue::Long(60),
+ sorted_order.data(), rm);
+
+ ASSERT_EQ(rm.size(), 6u);
+ ASSERT_EQ(rm.Get(0), 7u);
+}
+
+TEST(NumericStorageUnittest, CompareSortedIndexesEqual) {
+ std::vector<uint32_t> data_vec{30, 40, 50, 60, 90, 80, 70, 0, 10, 20};
+ std::vector<uint32_t> sorted_order{7, 8, 9, 0, 1, 2, 3, 6, 5, 4};
+
+ NumericStorage storage(data_vec.data(), 10, ColumnType::kUint32);
+ RowMap rm(0, 10);
+
+ storage.CompareSortedIndexes(FilterOp::kEq, SqlValue::Long(60),
+ sorted_order.data(), rm);
+
+ ASSERT_EQ(rm.size(), 1u);
+ ASSERT_EQ(rm.Get(0), 3u);
+}
+
+TEST(StorageOverlayUnittests, FilterIsNull) {
+ std::vector<uint32_t> data_vec(1025);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ NumericStorage storage(data_vec.data(), 1025, ColumnType::kUint32);
+ StorageOverlay overlay(&storage);
+
+ RowMap rm(0, 1025);
+ overlay.Filter(FilterOp::kIsNull, SqlValue::Long(0), rm);
+
+ ASSERT_EQ(rm.size(), 0u);
+}
+
+TEST(StorageOverlayUnittests, FilterIsNotNull) {
+ std::vector<uint32_t> data_vec(1025);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ NumericStorage storage(data_vec.data(), 1025, ColumnType::kUint32);
+ StorageOverlay overlay(&storage);
+
+ RowMap rm(0, 1025);
+ overlay.Filter(FilterOp::kIsNotNull, SqlValue::Long(0), rm);
+
+ ASSERT_EQ(rm.size(), 1025u);
+}
+
+TEST(StorageOverlayUnittests, Filter) {
+ std::vector<uint32_t> data_vec(1025);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ NumericStorage storage(data_vec.data(), 1025, ColumnType::kUint32);
+ StorageOverlay overlay(&storage);
+
+ RowMap rm(0, 1025);
+ overlay.Filter(FilterOp::kGe, SqlValue::Long(200), rm);
+
+ ASSERT_EQ(rm.size(), 825u);
+ ASSERT_EQ(rm.Get(0), 200u);
+}
+
+TEST(StorageOverlayUnittests, Sort) {
+ std::vector<uint32_t> data_vec{0, 1, 2, 0, 1, 2, 0, 1, 2};
+ std::vector<uint32_t> out = {1, 7, 4, 0, 6, 3, 2, 5, 8};
+
+ NumericStorage storage(data_vec.data(), 9, ColumnType::kUint32);
+ StorageOverlay overlay(&storage);
+
+ overlay.StableSort(out.data(), 9);
+
+ std::vector<uint32_t> stable_out{0, 6, 3, 1, 7, 4, 2, 5, 8};
+ ASSERT_EQ(out, stable_out);
+}
+
+TEST(NullOverlayUnittest, FilterIsNull) {
+ std::vector<uint32_t> data_vec(10);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ BitVector bv = BitVector::Range(0, 20, [](uint32_t t) { return t % 2 == 0; });
+
+ NumericStorage storage(data_vec.data(), 10, ColumnType::kUint32);
+ std::unique_ptr<ColumnOverlay> storage_overlay(new StorageOverlay(&storage));
+ NullOverlay overlay(std::move(storage_overlay), &bv);
+
+ RowMap rm(0, 10);
+ overlay.Filter(FilterOp::kIsNull, SqlValue::Long(5), rm);
+ ASSERT_EQ(rm.size(), 5u);
+ ASSERT_EQ(rm.Get(0), 1u);
+}
+
+TEST(NullOverlayUnittest, FilterIsNotNull) {
+ std::vector<uint32_t> data_vec(10);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ NumericStorage storage(data_vec.data(), 10, ColumnType::kUint32);
+ BitVector bv = BitVector::Range(0, 20, [](uint32_t t) { return t % 2 == 0; });
+ std::unique_ptr<ColumnOverlay> storage_overlay(new StorageOverlay(&storage));
+ NullOverlay overlay(std::move(storage_overlay), &bv);
+
+ RowMap rm(0, 10);
+ overlay.Filter(FilterOp::kIsNotNull, SqlValue::Long(5), rm);
+
+ ASSERT_EQ(rm.size(), 5u);
+ ASSERT_EQ(rm.Get(0), 0u);
+}
+
+TEST(NullOverlayUnittest, Filter) {
+ uint32_t bv_size = 20;
+ uint32_t data_size = 10;
+
+ // Prepare storage
+ std::vector<uint32_t> data_vec(data_size);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ NumericStorage storage(data_vec.data(), data_size, ColumnType::kUint32);
+
+ // Prepare NullOverlay
+ BitVector bv =
+ BitVector::Range(0, bv_size, [](uint32_t t) { return t % 2 == 0; });
+ std::unique_ptr<ColumnOverlay> storage_overlay(new StorageOverlay(&storage));
+ NullOverlay overlay(std::move(storage_overlay), &bv);
+
+ RowMap rm(0, bv_size);
+ overlay.Filter(FilterOp::kGe, SqlValue::Long(5), rm);
+
+ ASSERT_EQ(rm.size(), 5u);
+ ASSERT_EQ(rm.Get(0), 10u);
+}
+
+TEST(NullOverlayUnittest, FilterLarge) {
+ uint32_t bv_size = 1000;
+ uint32_t data_size = 100;
+
+ // Prepare storage
+ std::vector<uint32_t> data_vec(data_size);
+ std::iota(data_vec.begin(), data_vec.end(), 0);
+ NumericStorage storage(data_vec.data(), data_size, ColumnType::kUint32);
+
+ // Prepare NullOverlay
+ BitVector bv =
+ BitVector::Range(800, bv_size, [](uint32_t t) { return t % 2 == 0; });
+ std::unique_ptr<ColumnOverlay> storage_overlay(new StorageOverlay(&storage));
+ NullOverlay overlay(std::move(storage_overlay), &bv);
+
+ RowMap rm(0, bv_size);
+ overlay.Filter(FilterOp::kGe, SqlValue::Long(50), rm);
+
+ ASSERT_EQ(rm.size(), 50u);
+ ASSERT_EQ(rm.Get(0), 900u);
+}
+
+TEST(NullOverlayUnittest, Sort) {
+ // Prepare storage
+ std::vector<uint32_t> data_vec{0, 1, 2, 0, 1, 2, 0, 1, 2};
+ std::vector<uint32_t> out(18);
+ std::iota(out.begin(), out.end(), 0);
+ NumericStorage storage(data_vec.data(), 9, ColumnType::kUint32);
+
+ // Prepare NullOverlay
+ BitVector bv = BitVector::Range(0, 18, [](uint32_t t) { return t % 2 == 0; });
+ std::unique_ptr<ColumnOverlay> storage_overlay(new StorageOverlay(&storage));
+ NullOverlay overlay(std::move(storage_overlay), &bv);
+
+ overlay.StableSort(out.data(), 18);
+
+ std::vector<uint32_t> stable_out{1, 3, 5, 7, 9, 11, 13, 15, 17,
+ 0, 6, 12, 2, 8, 14, 4, 10, 16};
+ ASSERT_EQ(out, stable_out);
+}
+
} // namespace
} // namespace column
} // namespace trace_processor
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index d0d58ba..ec5f264 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -71,6 +71,7 @@
#include "protos/perfetto/trace/ftrace/signal.pbzero.h"
#include "protos/perfetto/trace/ftrace/skb.pbzero.h"
#include "protos/perfetto/trace/ftrace/sock.pbzero.h"
+#include "protos/perfetto/trace/ftrace/synthetic.pbzero.h"
#include "protos/perfetto/trace/ftrace/systrace.pbzero.h"
#include "protos/perfetto/trace/ftrace/task.pbzero.h"
#include "protos/perfetto/trace/ftrace/tcp.pbzero.h"
@@ -232,6 +233,10 @@
cpu_idle_name_id_(context->storage->InternString("cpuidle")),
suspend_resume_name_id_(
context->storage->InternString("Suspend/Resume Latency")),
+ suspend_resume_minimal_name_id_(
+ context->storage->InternString("Suspend/Resume Minimal")),
+ suspend_resume_minimal_slice_name_id_(
+ context->storage->InternString("Suspended")),
kfree_skb_name_id_(context->storage->InternString("Kfree Skb IP Prot")),
ion_total_id_(context->storage->InternString("mem.ion")),
ion_change_id_(context->storage->InternString("mem.ion_change")),
@@ -870,6 +875,10 @@
ParseSuspendResume(ts, fld_bytes);
break;
}
+ case FtraceEvent::kSuspendResumeMinimalFieldNumber: {
+ ParseSuspendResumeMinimal(ts, fld_bytes);
+ break;
+ }
case FtraceEvent::kDrmVblankEventFieldNumber:
case FtraceEvent::kDrmVblankEventDeliveredFieldNumber:
case FtraceEvent::kDrmSchedJobFieldNumber:
@@ -2924,6 +2933,26 @@
ongoing_suspend_resume_actions[current_action] = true;
}
+void FtraceParser::ParseSuspendResumeMinimal(int64_t timestamp,
+ protozero::ConstBytes blob) {
+ protos::pbzero::SuspendResumeMinimalFtraceEvent::Decoder evt(blob.data,
+ blob.size);
+ auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
+ suspend_resume_minimal_name_id_);
+
+ if (evt.start()) {
+ TrackId start_id = context_->async_track_set_tracker->Begin(
+ async_track, static_cast<int64_t>(0));
+ context_->slice_tracker->Begin(timestamp, start_id,
+ suspend_resume_minimal_name_id_,
+ suspend_resume_minimal_slice_name_id_);
+ } else {
+ TrackId end_id = context_->async_track_set_tracker->End(
+ async_track, static_cast<int64_t>(0));
+ context_->slice_tracker->End(timestamp, end_id);
+ }
+}
+
void FtraceParser::ParseSchedCpuUtilCfs(int64_t timestamp,
protozero::ConstBytes blob) {
protos::pbzero::SchedCpuUtilCfsFtraceEvent::Decoder evt(blob.data, blob.size);
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index abfb0e3..ccb40f8 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -216,6 +216,7 @@
void ParseWakeSourceActivate(int64_t timestamp, protozero::ConstBytes);
void ParseWakeSourceDeactivate(int64_t timestamp, protozero::ConstBytes);
void ParseSuspendResume(int64_t timestamp, protozero::ConstBytes);
+ void ParseSuspendResumeMinimal(int64_t timestamp, protozero::ConstBytes);
void ParseSchedCpuUtilCfs(int64_t timestap, protozero::ConstBytes);
void ParseFuncgraphEntry(int64_t timestamp,
@@ -288,6 +289,8 @@
const StringId gpu_freq_name_id_;
const StringId cpu_idle_name_id_;
const StringId suspend_resume_name_id_;
+ const StringId suspend_resume_minimal_name_id_;
+ const StringId suspend_resume_minimal_slice_name_id_;
const StringId kfree_skb_name_id_;
const StringId ion_total_id_;
const StringId ion_change_id_;
diff --git a/src/trace_processor/importers/proto/android_probes_module.cc b/src/trace_processor/importers/proto/android_probes_module.cc
index 94a9cb5..fece007 100644
--- a/src/trace_processor/importers/proto/android_probes_module.cc
+++ b/src/trace_processor/importers/proto/android_probes_module.cc
@@ -181,7 +181,9 @@
: packet_timestamp;
protozero::HeapBuffered<protos::pbzero::TracePacket> data_packet;
- data_packet->set_timestamp(static_cast<uint64_t>(actual_ts));
+ // Keep the original timestamp to later extract as an arg; the sorter does
+ // not read this.
+ data_packet->set_timestamp(static_cast<uint64_t>(packet_timestamp));
auto* energy = data_packet->set_power_rails()->add_energy_data();
energy->set_energy(data.energy());
@@ -207,7 +209,7 @@
parser_.ParseBatteryCounters(ts, decoder.battery());
return;
case TracePacket::kPowerRailsFieldNumber:
- parser_.ParsePowerRails(ts, decoder.power_rails());
+ parser_.ParsePowerRails(ts, decoder.timestamp(), decoder.power_rails());
return;
case TracePacket::kAndroidEnergyEstimationBreakdownFieldNumber:
parser_.ParseEnergyBreakdown(
diff --git a/src/trace_processor/importers/proto/android_probes_parser.cc b/src/trace_processor/importers/proto/android_probes_parser.cc
index 7521061..b165a2b 100644
--- a/src/trace_processor/importers/proto/android_probes_parser.cc
+++ b/src/trace_processor/importers/proto/android_probes_parser.cc
@@ -62,7 +62,8 @@
screen_state_id_(context->storage->InternString("ScreenState")),
device_state_id_(context->storage->InternString("DeviceStateChanged")),
battery_status_id_(context->storage->InternString("BatteryStatus")),
- plug_type_id_(context->storage->InternString("PlugType")) {}
+ plug_type_id_(context->storage->InternString("PlugType")),
+ rail_packet_timestamp_id_(context->storage->InternString("packet_ts")) {}
void AndroidProbesParser::ParseBatteryCounters(int64_t ts, ConstBytes blob) {
protos::pbzero::BatteryCounters::Decoder evt(blob.data, blob.size);
@@ -118,7 +119,9 @@
}
}
-void AndroidProbesParser::ParsePowerRails(int64_t ts, ConstBytes blob) {
+void AndroidProbesParser::ParsePowerRails(int64_t ts,
+ uint64_t trace_packet_ts,
+ ConstBytes blob) {
protos::pbzero::PowerRails::Decoder evt(blob.data, blob.size);
// Descriptors should have been processed at tokenization time.
@@ -134,12 +137,16 @@
auto opt_track = tracker->GetPowerRailTrack(desc.index());
if (opt_track.has_value()) {
// The tokenization makes sure that this field is always present and
- // is equal to the packet's timestamp (as the packet was forged in
- // the tokenizer).
+ // is equal to the packet's timestamp that was passed to us via the sorter.
PERFETTO_DCHECK(desc.has_timestamp_ms());
PERFETTO_DCHECK(ts / 1000000 == static_cast<int64_t>(desc.timestamp_ms()));
- context_->event_tracker->PushCounter(ts, static_cast<double>(desc.energy()),
- *opt_track);
+ auto maybe_counter_id = context_->event_tracker->PushCounter(
+ ts, static_cast<double>(desc.energy()), *opt_track);
+ if (maybe_counter_id) {
+ context_->args_tracker->AddArgsTo(*maybe_counter_id)
+ .AddArg(rail_packet_timestamp_id_,
+ Variadic::UnsignedInteger(trace_packet_ts));
+ }
} else {
context_->storage->IncrementStats(stats::power_rail_unknown_index);
}
diff --git a/src/trace_processor/importers/proto/android_probes_parser.h b/src/trace_processor/importers/proto/android_probes_parser.h
index 7ea91a1..06b1019 100644
--- a/src/trace_processor/importers/proto/android_probes_parser.h
+++ b/src/trace_processor/importers/proto/android_probes_parser.h
@@ -34,7 +34,7 @@
explicit AndroidProbesParser(TraceProcessorContext*);
void ParseBatteryCounters(int64_t ts, ConstBytes);
- void ParsePowerRails(int64_t ts, ConstBytes);
+ void ParsePowerRails(int64_t ts, uint64_t trace_packet_ts, ConstBytes);
void ParseEnergyBreakdown(int64_t ts, ConstBytes);
void ParseEntityStateResidency(int64_t ts, ConstBytes);
void ParseAndroidLogPacket(ConstBytes);
@@ -56,6 +56,7 @@
const StringId device_state_id_;
const StringId battery_status_id_;
const StringId plug_type_id_;
+ const StringId rail_packet_timestamp_id_;
};
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/chrome_system_probes_parser.h b/src/trace_processor/importers/proto/chrome_system_probes_parser.h
index 8c65fd4..b011fe5 100644
--- a/src/trace_processor/importers/proto/chrome_system_probes_parser.h
+++ b/src/trace_processor/importers/proto/chrome_system_probes_parser.h
@@ -43,7 +43,7 @@
// Maps a proto field number for memcounters in ProcessStats::Process to
// their StringId. Keep kProcStatsProcessSize equal to 1 + max proto field
// id of ProcessStats::Process. Also update SystemProbesParser.
- static constexpr size_t kProcStatsProcessSize = 15;
+ static constexpr size_t kProcStatsProcessSize = 21;
std::array<StringId, kProcStatsProcessSize> proc_stats_process_names_{};
};
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index fa1ffd6..b18bdea 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -357,7 +357,7 @@
// args in arrays.
std::stable_sort(interned.begin(), interned.end(),
[](const Arg& a, const Arg& b) {
- return a.first.raw_id() < b.second.raw_id();
+ return a.first.raw_id() < b.first.raw_id();
});
// Compute the correct key for each arg, possibly adding an index to
@@ -373,20 +373,16 @@
inserter->AddArg(key, Variadic::String(it->second));
} else {
constexpr size_t kMaxIndexSize = 20;
- base::StringView key_str = context_->storage->GetString(key);
+ NullTermStringView key_str = context_->storage->GetString(key);
if (key_str.size() >= sizeof(buffer) - kMaxIndexSize) {
PERFETTO_DLOG("Ignoring arg with unreasonbly large size");
continue;
}
- base::StringWriter writer(buffer, sizeof(buffer));
- writer.AppendString(key_str);
- writer.AppendChar('[');
- writer.AppendUnsignedInt(current_idx);
- writer.AppendChar(']');
-
+ base::StackString<2048> array_key("%s[%u]", key_str.c_str(),
+ current_idx);
StringId new_key =
- context_->storage->InternString(writer.GetStringView());
+ context_->storage->InternString(array_key.string_view());
inserter->AddArg(key, new_key, Variadic::String(it->second));
current_idx = key == next_key ? current_idx + 1 : 0;
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
index 999d365..da6a2d2 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ b/src/trace_processor/importers/proto/system_probes_parser.cc
@@ -153,6 +153,16 @@
context->storage->InternString("mem.rss.watermark");
proc_stats_process_names_[ProcessStats::Process::kOomScoreAdjFieldNumber] =
oom_score_adj_id_;
+ proc_stats_process_names_[ProcessStats::Process::kSmrRssKbFieldNumber] =
+ context->storage->InternString("mem.smaps.rss");
+ proc_stats_process_names_[ProcessStats::Process::kSmrPssKbFieldNumber] =
+ context->storage->InternString("mem.smaps.pss");
+ proc_stats_process_names_[ProcessStats::Process::kSmrPssAnonKbFieldNumber] =
+ context->storage->InternString("mem.smaps.pss.anon");
+ proc_stats_process_names_[ProcessStats::Process::kSmrPssFileKbFieldNumber] =
+ context->storage->InternString("mem.smaps.pss.file");
+ proc_stats_process_names_[ProcessStats::Process::kSmrPssShmemKbFieldNumber] =
+ context->storage->InternString("mem.smaps.pss.shmem");
}
void SystemProbesParser::ParseDiskStats(int64_t ts, ConstBytes blob) {
diff --git a/src/trace_processor/importers/proto/system_probes_parser.h b/src/trace_processor/importers/proto/system_probes_parser.h
index 77721d5..c1576a5 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.h
+++ b/src/trace_processor/importers/proto/system_probes_parser.h
@@ -72,7 +72,7 @@
// their StringId. Keep kProcStatsProcessSize equal to 1 + max proto field
// id of ProcessStats::Process. Also update the value in
// ChromeSystemProbesParser.
- static constexpr size_t kProcStatsProcessSize = 15;
+ static constexpr size_t kProcStatsProcessSize = 21;
std::array<StringId, kProcStatsProcessSize> proc_stats_process_names_{};
uint64_t ms_per_tick_ = 0;
diff --git a/src/trace_processor/metrics/metrics.h b/src/trace_processor/metrics/metrics.h
index 16e004c..2691e91 100644
--- a/src/trace_processor/metrics/metrics.h
+++ b/src/trace_processor/metrics/metrics.h
@@ -27,7 +27,7 @@
#include "perfetto/protozero/message.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
#include "perfetto/trace_processor/trace_processor.h"
-#include "src/trace_processor/prelude/functions/register_function.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
#include "src/trace_processor/util/descriptors.h"
#include "protos/perfetto/trace_processor/metrics_impl.pbzero.h"
diff --git a/src/trace_processor/metrics/sql/android/BUILD.gn b/src/trace_processor/metrics/sql/android/BUILD.gn
index bf54d44..a566661 100644
--- a/src/trace_processor/metrics/sql/android/BUILD.gn
+++ b/src/trace_processor/metrics/sql/android/BUILD.gn
@@ -82,6 +82,7 @@
"java_heap_histogram.sql",
"java_heap_stats.sql",
"mem_stats_priority_breakdown.sql",
+ "network_activity_template.sql",
"p_state.sql",
"power_drain_in_watts.sql",
"power_profile_data.sql",
diff --git a/src/trace_processor/metrics/sql/android/android_batt.sql b/src/trace_processor/metrics/sql/android/android_batt.sql
index 7dde099..b88d7ed 100644
--- a/src/trace_processor/metrics/sql/android/android_batt.sql
+++ b/src/trace_processor/metrics/sql/android/android_batt.sql
@@ -49,8 +49,16 @@
)
GROUP BY group_id;
+DROP VIEW IF EXISTS suspend_slice_from_minimal;
+CREATE VIEW suspend_slice_from_minimal AS
+SELECT ts, dur
+FROM track t JOIN slice s ON s.track_id = t.id
+WHERE t.name = 'Suspend/Resume Minimal';
+
DROP TABLE IF EXISTS suspend_slice_;
CREATE TABLE suspend_slice_ AS
+SELECT ts, dur FROM suspend_slice_from_minimal
+UNION ALL
SELECT
ts,
dur
@@ -62,7 +70,10 @@
WHERE
track.name = 'Suspend/Resume Latency'
AND (slice.name = 'syscore_resume(0)' OR slice.name = 'timekeeping_freeze(0)')
- AND dur != -1;
+ AND dur != -1
+ AND NOT EXISTS(SELECT * FROM suspend_slice_from_minimal);
+
+DROP VIEW suspend_slice_from_minimal;
SELECT RUN_METRIC('android/counter_span_view_merged.sql',
'table_name', 'screen_state',
diff --git a/src/trace_processor/metrics/sql/android/android_binder.sql b/src/trace_processor/metrics/sql/android/android_binder.sql
index 1d15050..f59f5d9 100644
--- a/src/trace_processor/metrics/sql/android/android_binder.sql
+++ b/src/trace_processor/metrics/sql/android/android_binder.sql
@@ -45,11 +45,13 @@
'client_ts', client_ts,
'client_dur', client_dur,
'client_tid', client_tid,
+ 'client_pid', client_pid,
'server_process', server_process,
'server_thread', server_thread,
'server_ts', server_ts,
'server_dur', server_dur,
'server_tid', server_tid,
+ 'server_pid', server_pid,
'thread_states', (
SELECT RepeatedField(
AndroidBinderMetric_ThreadStateBreakdown(
diff --git a/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_metric.sql b/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_metric.sql
index 7c56db2..3538f7d 100644
--- a/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_metric.sql
+++ b/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_metric.sql
@@ -20,6 +20,7 @@
SELECT RUN_METRIC('android/android_jank_cuj.sql');
SELECT IMPORT('android.slices');
+SELECT IMPORT('android.binder');
-- Jank "J<*>" and latency "L<*>" cujs are put together in android_cujs table.
-- They are computed separately as latency ones are slightly different, don't
@@ -75,6 +76,24 @@
FROM all_cujs;
+DROP TABLE IF EXISTS relevant_binder_calls_with_names;
+CREATE TABLE relevant_binder_calls_with_names AS
+SELECT DISTINCT
+ tx.aidl_name AS name,
+ tx.client_ts AS ts,
+ s.track_id,
+ tx.client_dur AS dur,
+ s.id,
+ tx.client_process as process_name,
+ tx.client_utid as utid,
+ tx.client_upid as upid
+FROM android_sync_binder_metrics_by_txn AS tx
+ JOIN slice AS s ON s.id = tx.binder_txn_id
+ -- Keeps only slices in cuj processes.
+ JOIN android_cujs ON tx.client_upid = android_cujs.upid
+WHERE is_main_thread AND aidl_name IS NOT NULL;
+
+
DROP TABLE IF EXISTS android_blocking_calls_cuj_calls;
CREATE TABLE android_blocking_calls_cuj_calls AS
WITH all_main_thread_relevant_slices AS (
@@ -108,6 +127,17 @@
OR s.name GLOB 'relayoutWindow*'
OR s.name GLOB 'ImageDecoder#decode*'
)
+ UNION ALL
+ SELECT
+ name,
+ ts,
+ track_id,
+ dur,
+ id,
+ process_name,
+ utid,
+ upid
+ FROM relevant_binder_calls_with_names
),
-- Now we have:
-- (1) a list of slices from the main thread of each process
diff --git a/src/trace_processor/metrics/sql/android/android_monitor_contention.sql b/src/trace_processor/metrics/sql/android/android_monitor_contention.sql
index 7cfaeb8..52e1693 100644
--- a/src/trace_processor/metrics/sql/android/android_monitor_contention.sql
+++ b/src/trace_processor/metrics/sql/android/android_monitor_contention.sql
@@ -35,7 +35,10 @@
'waiter_count', waiter_count,
'blocking_thread_name', blocking_thread_name,
'blocked_thread_name', blocked_thread_name,
+ 'blocked_thread_tid', blocked_thread_tid,
+ 'blocking_thread_tid', blocking_thread_tid,
'process_name', process_name,
+ 'pid', pid,
'is_blocked_thread_main', is_blocked_thread_main,
'is_blocking_thread_main', is_blocking_thread_main,
'binder_reply_ts', binder_reply_ts,
diff --git a/src/trace_processor/metrics/sql/android/android_startup.sql b/src/trace_processor/metrics/sql/android/android_startup.sql
index ab76b6c..892f6be 100644
--- a/src/trace_processor/metrics/sql/android/android_startup.sql
+++ b/src/trace_processor/metrics/sql/android/android_startup.sql
@@ -213,6 +213,10 @@
DUR_SUM_MAIN_THREAD_SLICE_PROTO_FOR_LAUNCH(
launches.startup_id,
'OpenDexFilesFromOat*'),
+ 'time_dlopen_thread_main',
+ DUR_SUM_MAIN_THREAD_SLICE_PROTO_FOR_LAUNCH(
+ launches.startup_id,
+ 'dlopen:*.so'),
'time_lock_contention_thread_main',
DUR_SUM_MAIN_THREAD_SLICE_PROTO_FOR_LAUNCH(
launches.startup_id,
@@ -298,6 +302,11 @@
WHERE l.startup_id != launches.startup_id
AND IS_SPANS_OVERLAPPING(l.ts, l.ts_end, launches.ts, launches.ts_end)
),
+ 'dlopen_file', (
+ SELECT RepeatedField(STR_SPLIT(slice_name, "dlopen: ", 1))
+ FROM android_thread_slices_for_all_startups s
+ WHERE startup_id = launches.startup_id AND slice_name GLOB "dlopen: *.so"
+ ),
'system_state', AndroidStartupMetric_SystemState(
'dex2oat_running',
DUR_OF_PROCESS_RUNNING_CONCURRENT_TO_LAUNCH(launches.startup_id, '*dex2oat64') > 0,
diff --git a/src/trace_processor/metrics/sql/android/java_heap_stats.sql b/src/trace_processor/metrics/sql/android/java_heap_stats.sql
index 15627b4..32c43f4 100644
--- a/src/trace_processor/metrics/sql/android/java_heap_stats.sql
+++ b/src/trace_processor/metrics/sql/android/java_heap_stats.sql
@@ -65,7 +65,7 @@
SELECT * FROM base_stat_counts JOIN heap_roots_proto USING (upid, graph_sample_ts)
),
-- Find closest value
-closest_anon_swap AS (
+closest_anon_swap_oom AS (
SELECT
upid,
graph_sample_ts,
@@ -84,7 +84,23 @@
-- accept it if close (500ms)
OR (graph_sample_ts < ts AND diff <= 500 * 1e6)
ORDER BY diff LIMIT 1
- ) AS val
+ ) AS anon_swap_val,
+ (
+ SELECT oom_score_val
+ FROM (
+ SELECT
+ ts, dur,
+ oom_score_val,
+ ABS(ts - base_stats.graph_sample_ts) AS diff
+ FROM oom_score_span
+ WHERE upid = base_stats.upid)
+ WHERE
+ (graph_sample_ts >= ts AND graph_sample_ts < ts + dur)
+ -- If the first memory sample for the UPID comes *after* the heap profile
+ -- accept it if close (500ms)
+ OR (graph_sample_ts < ts AND diff <= 500 * 1e6)
+ ORDER BY diff LIMIT 1
+ ) AS oom_score_val
FROM base_stats
),
-- Group by upid
@@ -100,10 +116,11 @@
'reachable_heap_native_size', reachable_native_size,
'reachable_obj_count', reachable_obj_count,
'roots', roots,
- 'anon_rss_and_swap_size', closest_anon_swap.val
+ 'anon_rss_and_swap_size', closest_anon_swap_oom.anon_swap_val,
+ 'oom_score_adj', closest_anon_swap_oom.oom_score_val
)) AS sample_protos
FROM base_stats
- LEFT JOIN closest_anon_swap USING (upid, graph_sample_ts)
+ LEFT JOIN closest_anon_swap_oom USING (upid, graph_sample_ts)
GROUP BY 1
)
SELECT JavaHeapStats(
diff --git a/src/trace_processor/metrics/sql/android/network_activity_template.sql b/src/trace_processor/metrics/sql/android/network_activity_template.sql
new file mode 100644
index 0000000..2dcfa31
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/network_activity_template.sql
@@ -0,0 +1,74 @@
+--
+-- Copyright 2023 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.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 IMPORT('android.network_packets');
+
+-- Creates a view of aggregated network activity. It is common among networking
+-- to have the interface active for some time after network use. For example, in
+-- mobile networking, it is common to have the cellular interface active for 10
+-- or more seconds after the last packet was sent or received. This view takes
+-- raw packet timing and aggregates it into something that approximates the
+-- activity of the underlying interface.
+--
+-- @arg view_name The name of the output view.
+-- @arg group_by Expression to group by (set to 'null' for no grouping).
+-- @arg filter Expression on `android_network_packets` to filter by.
+-- @arg idle_ns The amount of time before considering the network idle.
+-- @arg quant_ns Quantization value, to group rows before the heavy
+-- part of the query. This should be smaller than idle_ns.
+--
+-- @column group_by The group_by columns are all present in the output.
+-- @column ts The timestamp indicating the start of the segment.
+-- @column dur The duration of the current segment.
+-- @column packet_count The total number of packets in this segment.
+-- @column packet_length The total number of bytes for packets in this segment.
+CREATE VIEW {{view_name}} AS
+WITH quantized AS (
+ SELECT
+ {{group_by}},
+ MIN(ts) AS ts,
+ MAX(ts+dur)-MIN(ts) AS dur,
+ SUM(packet_count) AS packet_count,
+ SUM(packet_length) AS packet_length
+ FROM android_network_packets
+ WHERE {{filter}}
+ GROUP BY CAST(ts / {{quant_ns}} AS INT64), {{group_by}}
+),
+with_last AS (
+ SELECT
+ *,
+ LAG(ts) OVER (
+ PARTITION BY {{group_by}}
+ ORDER BY ts
+ ) AS last_ts
+ FROM quantized
+),
+with_group AS (
+ SELECT
+ *,
+ COUNT(IIF(ts-last_ts>{{idle_ns}}, 1, null)) OVER (
+ PARTITION BY {{group_by}}
+ ORDER BY ts
+ ) AS group_id
+ FROM with_last
+)
+SELECT
+ {{group_by}},
+ MIN(ts) AS ts,
+ MAX(ts+dur)-MIN(ts)+{{idle_ns}} AS dur,
+ SUM(packet_count) AS packet_count,
+ SUM(packet_length) AS packet_length
+FROM with_group
+GROUP BY group_id, {{group_by}}
diff --git a/src/trace_processor/metrics/sql/android/process_metadata.sql b/src/trace_processor/metrics/sql/android/process_metadata.sql
index acaceb7..5ccf2b1 100644
--- a/src/trace_processor/metrics/sql/android/process_metadata.sql
+++ b/src/trace_processor/metrics/sql/android/process_metadata.sql
@@ -18,7 +18,8 @@
DROP VIEW IF EXISTS process_metadata_table;
CREATE VIEW process_metadata_table AS
-SELECT * FROM android_process_metadata;
+SELECT android_process_metadata.*, pid FROM android_process_metadata
+JOIN process USING(upid);
DROP VIEW IF EXISTS uid_package_count;
CREATE VIEW uid_package_count AS
@@ -43,6 +44,7 @@
NULL_IF_EMPTY(AndroidProcessMetadata(
'name', process_name,
'uid', uid,
+ 'pid', pid,
'package', NULL_IF_EMPTY(AndroidProcessMetadata_Package(
'package_name', package_name,
'apk_version_code', version_code,
diff --git a/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql b/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql
index b3939bb..4ef1fc4 100644
--- a/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql
+++ b/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql
@@ -38,8 +38,10 @@
CREATE TABLE launch_thread_state_io_wait_dur_sum AS
SELECT startup_id, state, is_main_thread, thread_name, io_wait, SUM(dur) AS dur
FROM launch_threads_by_thread_state l
+JOIN android_startup_processes p USING (startup_id)
WHERE
- is_main_thread
+ -- If it is a main thread, only add it if it is the lauching thread.
+ (is_main_thread AND p.startup_type NOT NULL)
-- Allowlist specific threads which need this. Do not add to this list
-- without careful consideration as every thread added here can cause
-- memory usage to balloon.
diff --git a/src/trace_processor/metrics/sql/chrome/chrome_tasks_template.sql b/src/trace_processor/metrics/sql/chrome/chrome_tasks_template.sql
index d2886f1..b5464cf 100644
--- a/src/trace_processor/metrics/sql/chrome/chrome_tasks_template.sql
+++ b/src/trace_processor/metrics/sql/chrome/chrome_tasks_template.sql
@@ -427,6 +427,7 @@
WHERE
s1.posted_from IN (
"mojo/public/cpp/system/simple_watcher.cc:Notify",
+ "mojo/public/cpp/system/simple_watcher.cc:ArmOrNotify",
"mojo/public/cpp/bindings/lib/connector.cc:PostDispatchNextMessageFromPipe",
"ipc/ipc_mojo_bootstrap.cc:Accept")
),
diff --git a/src/trace_processor/prelude/functions/BUILD.gn b/src/trace_processor/prelude/functions/BUILD.gn
index f7f2cd7..f2f22ba 100644
--- a/src/trace_processor/prelude/functions/BUILD.gn
+++ b/src/trace_processor/prelude/functions/BUILD.gn
@@ -31,8 +31,6 @@
"layout_functions.h",
"pprof_functions.cc",
"pprof_functions.h",
- "register_function.cc",
- "register_function.h",
"sqlite3_str_split.cc",
"sqlite3_str_split.h",
"stack_functions.cc",
@@ -59,7 +57,7 @@
"../../importers/common",
"../../importers/ftrace:ftrace_descriptors",
"../../prelude/table_functions",
- "../../sqlite:sqlite_minimal",
+ "../../sqlite",
"../../storage",
"../../types",
"../../util",
@@ -67,6 +65,20 @@
"../../util:sql_argument",
"../../util:stdlib",
]
+ public_deps = [ ":interface" ]
+}
+
+source_set("interface") {
+ sources = [
+ "sql_function.cc",
+ "sql_function.h",
+ ]
+ deps = [
+ "../../../../gn:default_deps",
+ "../../../../gn:sqlite",
+ "../../../../include/perfetto/trace_processor:basic_types",
+ "../../../base",
+ ]
}
perfetto_unittest_source_set("unittests") {
@@ -78,6 +90,6 @@
"../../../../gn:gtest_and_gmock",
"../../../../gn:sqlite",
"../../../base",
- "../../sqlite:sqlite_minimal",
+ "../../sqlite",
]
}
diff --git a/src/trace_processor/prelude/functions/clock_functions.h b/src/trace_processor/prelude/functions/clock_functions.h
index 34f23f2..aac6280 100644
--- a/src/trace_processor/prelude/functions/clock_functions.h
+++ b/src/trace_processor/prelude/functions/clock_functions.h
@@ -25,7 +25,7 @@
#include "src/trace_processor/prelude/functions/create_function_internal.h"
#include "src/trace_processor/util/status_macros.h"
-#include "src/trace_processor/prelude/functions/register_function.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
namespace perfetto {
namespace trace_processor {
diff --git a/src/trace_processor/prelude/functions/create_function.cc b/src/trace_processor/prelude/functions/create_function.cc
index ee2e733..c90ad9a 100644
--- a/src/trace_processor/prelude/functions/create_function.cc
+++ b/src/trace_processor/prelude/functions/create_function.cc
@@ -20,6 +20,7 @@
#include "perfetto/trace_processor/basic_types.h"
#include "src/trace_processor/prelude/functions/create_function_internal.h"
#include "src/trace_processor/sqlite/scoped_db.h"
+#include "src/trace_processor/sqlite/sqlite_engine.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/tp_metatrace.h"
#include "src/trace_processor/util/status_macros.h"
@@ -31,11 +32,11 @@
struct CreatedFunction : public SqlFunction {
struct Context {
- sqlite3* db;
+ SqliteEngine* engine;
Prototype prototype;
sql_argument::Type return_type;
std::string sql;
- sqlite3_stmt* stmt;
+ ScopedStmt stmt;
};
static base::Status Run(Context* ctx,
@@ -88,20 +89,21 @@
// Bind all the arguments to the appropriate places in the function.
for (size_t i = 0; i < argc; ++i) {
- RETURN_IF_ERROR(MaybeBindArgument(ctx->stmt, ctx->prototype.function_name,
+ RETURN_IF_ERROR(MaybeBindArgument(ctx->stmt.get(),
+ ctx->prototype.function_name,
ctx->prototype.arguments[i], argv[i]));
}
- int ret = sqlite3_step(ctx->stmt);
+ int ret = sqlite3_step(ctx->stmt.get());
RETURN_IF_ERROR(
- SqliteRetToStatus(ctx->db, ctx->prototype.function_name, ret));
+ SqliteRetToStatus(ctx->engine->db(), ctx->prototype.function_name, ret));
if (ret == SQLITE_DONE) {
// No return value means we just return don't set |out|.
return base::OkStatus();
}
PERFETTO_DCHECK(ret == SQLITE_ROW);
- size_t col_count = static_cast<size_t>(sqlite3_column_count(ctx->stmt));
+ size_t col_count = static_cast<size_t>(sqlite3_column_count(ctx->stmt.get()));
if (col_count != 1) {
return base::ErrStatus(
"%s: SQL definition should only return one column: returned %zu "
@@ -109,7 +111,8 @@
ctx->prototype.function_name.c_str(), col_count);
}
- out = sqlite_utils::SqliteValueToSqlValue(sqlite3_column_value(ctx->stmt, 0));
+ out = sqlite_utils::SqliteValueToSqlValue(
+ sqlite3_column_value(ctx->stmt.get(), 0));
// If we return a bytes type but have a null pointer, SQLite will convert this
// to an SQL null. However, for proto build functions, we actively want to
@@ -123,11 +126,11 @@
}
base::Status CreatedFunction::VerifyPostConditions(Context* ctx) {
- int ret = sqlite3_step(ctx->stmt);
+ int ret = sqlite3_step(ctx->stmt.get());
RETURN_IF_ERROR(
- SqliteRetToStatus(ctx->db, ctx->prototype.function_name, ret));
+ SqliteRetToStatus(ctx->engine->db(), ctx->prototype.function_name, ret));
if (ret == SQLITE_ROW) {
- auto expanded_sql = sqlite_utils::ExpandedSqlForStmt(ctx->stmt);
+ auto expanded_sql = sqlite_utils::ExpandedSqlForStmt(ctx->stmt.get());
return base::ErrStatus(
"%s: multiple values were returned when executing function body. "
"Executed SQL was %s",
@@ -138,21 +141,13 @@
}
void CreatedFunction::Cleanup(CreatedFunction::Context* ctx) {
- sqlite3_reset(ctx->stmt);
- sqlite3_clear_bindings(ctx->stmt);
+ sqlite3_reset(ctx->stmt.get());
+ sqlite3_clear_bindings(ctx->stmt.get());
}
} // namespace
-size_t CreateFunction::NameAndArgc::Hasher::operator()(
- const NameAndArgc& s) const noexcept {
- base::Hasher hash;
- hash.Update(s.name.data(), s.name.size());
- hash.Update(s.argc);
- return static_cast<size_t>(hash.digest());
-}
-
-base::Status CreateFunction::Run(CreateFunction::Context* ctx,
+base::Status CreateFunction::Run(SqliteEngine* engine,
size_t argc,
sqlite3_value** argv,
SqlValue&,
@@ -216,16 +211,14 @@
}
int created_argc = static_cast<int>(prototype.arguments.size());
- NameAndArgc key{prototype.function_name, created_argc};
- auto it = ctx->state->find(key);
- if (it != ctx->state->end()) {
+ auto* fn_ctx =
+ engine->GetFunctionContext(prototype.function_name, created_argc);
+ if (fn_ctx) {
// If the function already exists, just verify that the prototype, return
// type and SQL matches exactly with what we already had registered. By
// doing this, we can avoid the problem plaguing C++ macros where macro
// ordering determines which one gets run.
- auto* created_ctx = static_cast<CreatedFunction::Context*>(
- it->second.created_functon_context);
-
+ auto* created_ctx = static_cast<CreatedFunction::Context*>(fn_ctx);
if (created_ctx->prototype != prototype) {
return base::ErrStatus(
"CREATE_FUNCTION[prototype=%s]: function prototype changed",
@@ -252,7 +245,7 @@
// Prepare the SQL definition as a statement using SQLite.
ScopedStmt stmt;
sqlite3_stmt* stmt_raw = nullptr;
- int ret = sqlite3_prepare_v2(ctx->db, sql_defn_str.data(),
+ int ret = sqlite3_prepare_v2(engine->db(), sql_defn_str.data(),
static_cast<int>(sql_defn_str.size()), &stmt_raw,
nullptr);
if (ret != SQLITE_OK) {
@@ -261,19 +254,18 @@
"statement %s",
prototype_str.ToStdString().c_str(),
sqlite_utils::FormatErrorMessage(
- stmt_raw, base::StringView(sql_defn_str), ctx->db, ret)
+ stmt_raw, base::StringView(sql_defn_str), engine->db(), ret)
.c_message());
}
stmt.reset(stmt_raw);
- std::unique_ptr<CreatedFunction::Context> created(
- new CreatedFunction::Context{ctx->db, std::move(prototype),
+ std::string function_name = prototype.function_name;
+ std::unique_ptr<CreatedFunction::Context> created_fn_ctx(
+ new CreatedFunction::Context{engine, std::move(prototype),
*opt_return_type, std::move(sql_defn_str),
- stmt.get()});
- CreatedFunction::Context* created_ptr = created.get();
- RETURN_IF_ERROR(RegisterSqlFunction<CreatedFunction>(
- ctx->db, key.name.c_str(), created_argc, std::move(created)));
- ctx->state->emplace(key, PerFunctionState{std::move(stmt), created_ptr});
+ std::move(stmt)});
+ RETURN_IF_ERROR(engine->RegisterSqlFunction<CreatedFunction>(
+ function_name.c_str(), created_argc, std::move(created_fn_ctx)));
// CREATE_FUNCTION doesn't have a return value so just don't sent |out|.
return base::OkStatus();
diff --git a/src/trace_processor/prelude/functions/create_function.h b/src/trace_processor/prelude/functions/create_function.h
index 258c4bb..0dd6f4c 100644
--- a/src/trace_processor/prelude/functions/create_function.h
+++ b/src/trace_processor/prelude/functions/create_function.h
@@ -20,7 +20,9 @@
#include <sqlite3.h>
#include <unordered_map>
-#include "src/trace_processor/prelude/functions/register_function.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
+#include "src/trace_processor/sqlite/scoped_db.h"
+#include "src/trace_processor/sqlite/sqlite_table.h"
namespace perfetto {
namespace trace_processor {
@@ -34,25 +36,7 @@
// void* to avoid leaking state.
void* created_functon_context;
};
- struct NameAndArgc {
- std::string name;
- int argc;
-
- struct Hasher {
- std::size_t operator()(const NameAndArgc& s) const noexcept;
- };
- bool operator==(const NameAndArgc& other) const {
- return name == other.name && argc == other.argc;
- }
- };
- using State = std::unordered_map<NameAndArgc,
- CreateFunction::PerFunctionState,
- NameAndArgc::Hasher>;
-
- struct Context {
- sqlite3* db;
- State* state;
- };
+ using Context = SqliteEngine;
static constexpr bool kVoidReturn = true;
diff --git a/src/trace_processor/prelude/functions/create_view_function.cc b/src/trace_processor/prelude/functions/create_view_function.cc
index 335b99d..952924f 100644
--- a/src/trace_processor/prelude/functions/create_view_function.cc
+++ b/src/trace_processor/prelude/functions/create_view_function.cc
@@ -24,6 +24,7 @@
#include "perfetto/trace_processor/basic_types.h"
#include "src/trace_processor/prelude/functions/create_function_internal.h"
#include "src/trace_processor/sqlite/scoped_db.h"
+#include "src/trace_processor/sqlite/sqlite_engine.h"
#include "src/trace_processor/sqlite/sqlite_table.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/tp_metatrace.h"
@@ -34,19 +35,20 @@
namespace {
-class CreatedViewFunction : public SqliteTable {
+class CreatedViewFunction final
+ : public TypedSqliteTable<CreatedViewFunction, void*> {
public:
- class Cursor : public SqliteTable::Cursor {
+ class Cursor final : public SqliteTable::BaseCursor {
public:
explicit Cursor(CreatedViewFunction* table);
- ~Cursor() override;
+ ~Cursor() final;
- int Filter(const QueryConstraints& qc,
- sqlite3_value**,
- FilterHistory) override;
- int Next() override;
- int Eof() override;
- int Column(sqlite3_context* context, int N) override;
+ base::Status Filter(const QueryConstraints& qc,
+ sqlite3_value**,
+ FilterHistory);
+ base::Status Next();
+ bool Eof();
+ base::Status Column(sqlite3_context* context, int N);
private:
ScopedStmt scoped_stmt_;
@@ -57,19 +59,11 @@
};
CreatedViewFunction(sqlite3*, void*);
- ~CreatedViewFunction() override;
+ ~CreatedViewFunction() final;
- base::Status Init(int argc, const char* const* argv, Schema*) override;
- std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
- int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) override;
-
- static void Register(sqlite3* db) {
- RegistrationFlags flags;
- flags.type = RegistrationFlags::kExplicitCreateStateless;
-
- SqliteTable::Register<CreatedViewFunction>(
- db, nullptr, "internal_view_function_impl", flags);
- }
+ base::Status Init(int argc, const char* const* argv, Schema*) final;
+ std::unique_ptr<SqliteTable::BaseCursor> CreateCursor() final;
+ int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) final;
private:
Schema CreateSchema();
@@ -249,7 +243,7 @@
return SqliteTable::Schema(std::move(columns), std::move(primary_keys));
}
-std::unique_ptr<SqliteTable::Cursor> CreatedViewFunction::CreateCursor() {
+std::unique_ptr<SqliteTable::BaseCursor> CreatedViewFunction::CreateCursor() {
return std::unique_ptr<Cursor>(new Cursor(this));
}
@@ -275,13 +269,13 @@
}
CreatedViewFunction::Cursor::Cursor(CreatedViewFunction* table)
- : SqliteTable::Cursor(table), table_(table) {}
+ : SqliteTable::BaseCursor(table), table_(table) {}
CreatedViewFunction::Cursor::~Cursor() = default;
-int CreatedViewFunction::Cursor::Filter(const QueryConstraints& qc,
- sqlite3_value** argv,
- FilterHistory) {
+base::Status CreatedViewFunction::Cursor::Filter(const QueryConstraints& qc,
+ sqlite3_value** argv,
+ FilterHistory) {
PERFETTO_TP_TRACE(metatrace::Category::FUNCTION, "CREATE_VIEW_FUNCTION",
[this](metatrace::Record* r) {
r->AddArg("Function",
@@ -305,10 +299,8 @@
// We only support equality constraints as we're expecting "input arguments"
// to our "function".
if (!sqlite_utils::IsOpEq(cs.op)) {
- table_->SetErrorMessage(
- sqlite3_mprintf("%s: non-equality constraint passed",
- table_->prototype_.function_name.c_str()));
- return SQLITE_ERROR;
+ return base::ErrStatus("%s: non-equality constraint passed",
+ table_->prototype_.function_name.c_str());
}
const auto& arg = table_->prototype_.arguments[col_to_arg_idx(cs.column)];
@@ -316,11 +308,9 @@
argv[i], sql_argument::TypeToSqlValueType(arg.type()),
sql_argument::TypeToHumanFriendlyString(arg.type()));
if (!status.ok()) {
- table_->SetErrorMessage(
- sqlite3_mprintf("%s: argument %s (index %u) %s",
- table_->prototype_.function_name.c_str(),
- arg.name().c_str(), i, status.c_message()));
- return SQLITE_ERROR;
+ return base::ErrStatus("%s: argument %s (index %zu) %s",
+ table_->prototype_.function_name.c_str(),
+ arg.name().c_str(), i, status.c_message());
}
seen_argument_constraints++;
@@ -328,12 +318,11 @@
// Verify that we saw one valid constriant for every input argument.
if (seen_argument_constraints < table_->prototype_.arguments.size()) {
- table_->SetErrorMessage(sqlite3_mprintf(
- "%s: missing value for input argument. Saw %u arguments but expected "
- "%u",
+ return base::ErrStatus(
+ "%s: missing value for input argument. Saw %zu arguments but expected "
+ "%zu",
table_->prototype_.function_name.c_str(), seen_argument_constraints,
- table_->prototype_.arguments.size()));
- return SQLITE_ERROR;
+ table_->prototype_.arguments.size());
}
// Prepare the SQL definition as a statement using SQLite.
@@ -364,10 +353,7 @@
const auto& arg = table_->prototype_.arguments[index];
auto status = MaybeBindArgument(stmt_, table_->prototype_.function_name,
arg, argv[i]);
- if (!status.ok()) {
- table_->SetErrorMessage(sqlite3_mprintf("%s", status.c_message()));
- return SQLITE_ERROR;
- }
+ RETURN_IF_ERROR(status);
}
// Reset the next call count - this is necessary because the same cursor
@@ -376,26 +362,25 @@
return Next();
}
-int CreatedViewFunction::Cursor::Next() {
+base::Status CreatedViewFunction::Cursor::Next() {
int ret = sqlite3_step(stmt_);
is_eof_ = ret == SQLITE_DONE;
next_call_count_++;
if (ret != SQLITE_ROW && ret != SQLITE_DONE) {
- table_->SetErrorMessage(sqlite3_mprintf(
+ return base::ErrStatus(
"%s: SQLite error while stepping statement: %s",
table_->prototype_.function_name.c_str(),
sqlite_utils::FormatErrorMessage(stmt_, std::nullopt, table_->db_, ret)
- .c_message()));
- return ret;
+ .c_message());
}
- return SQLITE_OK;
+ return base::OkStatus();
}
-int CreatedViewFunction::Cursor::Eof() {
+bool CreatedViewFunction::Cursor::Eof() {
return is_eof_;
}
-int CreatedViewFunction::Cursor::Column(sqlite3_context* ctx, int i) {
+base::Status CreatedViewFunction::Cursor::Column(sqlite3_context* ctx, int i) {
size_t idx = static_cast<size_t>(i);
if (table_->IsReturnValueColumn(idx)) {
sqlite3_result_value(ctx, sqlite3_column_value(stmt_, i));
@@ -409,7 +394,7 @@
PERFETTO_DCHECK(table_->IsPrimaryKeyColumn(idx));
sqlite3_result_int(ctx, next_call_count_);
}
- return SQLITE_OK;
+ return base::OkStatus();
}
} // namespace
@@ -497,8 +482,10 @@
return base::OkStatus();
}
-void CreateViewFunction::RegisterTable(sqlite3* db) {
- CreatedViewFunction::Register(db);
+void RegisterCreateViewFunctionModule(SqliteEngine* engine) {
+ engine->RegisterVirtualTableModule<CreatedViewFunction>(
+ "internal_view_function_impl", nullptr,
+ SqliteTable::TableType::kExplicitCreate, false);
}
} // namespace trace_processor
diff --git a/src/trace_processor/prelude/functions/create_view_function.h b/src/trace_processor/prelude/functions/create_view_function.h
index c91817a..509ea5e 100644
--- a/src/trace_processor/prelude/functions/create_view_function.h
+++ b/src/trace_processor/prelude/functions/create_view_function.h
@@ -20,11 +20,13 @@
#include <sqlite3.h>
#include <unordered_map>
-#include "src/trace_processor/prelude/functions/register_function.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
namespace perfetto {
namespace trace_processor {
+class SqliteEngine;
+
// Implementation of CREATE_VIEW_FUNCTION SQL function.
// See https://perfetto.dev/docs/analysis/metrics#metric-helper-functions for
// usage of this function.
@@ -40,10 +42,10 @@
sqlite3_value** argv,
SqlValue& out,
Destructors&);
-
- static void RegisterTable(sqlite3* db);
};
+void RegisterCreateViewFunctionModule(SqliteEngine*);
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/prelude/functions/import.h b/src/trace_processor/prelude/functions/import.h
index 9773b5f..da40f5f 100644
--- a/src/trace_processor/prelude/functions/import.h
+++ b/src/trace_processor/prelude/functions/import.h
@@ -23,7 +23,7 @@
#include "perfetto/ext/base/flat_hash_map.h"
#include "perfetto/trace_processor/trace_processor.h"
-#include "src/trace_processor/prelude/functions/register_function.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
#include "src/trace_processor/util/sql_modules.h"
namespace perfetto {
diff --git a/src/trace_processor/prelude/functions/register_function.h b/src/trace_processor/prelude/functions/register_function.h
deleted file mode 100644
index acca3e6..0000000
--- a/src/trace_processor/prelude/functions/register_function.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_PRELUDE_FUNCTIONS_REGISTER_FUNCTION_H_
-#define SRC_TRACE_PROCESSOR_PRELUDE_FUNCTIONS_REGISTER_FUNCTION_H_
-
-#include <sqlite3.h>
-#include <memory>
-
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Prototype for a C++ function which can be registered with SQLite.
-//
-// Usage
-//
-// Define a subclass of this struct as follows:
-// struct YourFunction : public SqlFunction {
-// // Optional if you want a custom context object (i.e. an object
-// // passed in at registration time which will be passed to Run on
-// // every invocation)
-// struct YourContext { /* define context fields here */ };
-//
-// static base::Status Run(/* see parameters below */) {
-// /* function body here */
-// }
-//
-// static base::Status Cleanup(/* see parameters below */) {
-// /* function body here */
-// }
-// }
-//
-// Then, register this function with SQLite using RegisterFunction (see below);
-// you'll likely want to do this in TraceProcessorImpl:
-// RegisterFunction<YourFunction>(/* see arguments below */)
-struct SqlFunction {
- // The type of the context object which will be passed to the function.
- // Can be redefined in any sub-classes to override the context.
- using Context = void;
-
- // Indicates whether this function is "void" (i.e. doesn't actually want
- // to return a value). While the function will still return null in SQL
- // (because SQLite does not actually allow null functions), for accounting
- // purposes, this null will be ignored when verifying whether this statement
- // has any output.
- // Can be redefined in any sub-classes to override it.
- // If this is set to true, subclasses must not modify |out| or |destructors|.
- static constexpr bool kVoidReturn = false;
-
- // Struct which holds destructors for strings/bytes returned from the
- // function. Passed as an argument to |Run| to allow implementations to
- // override the destructors.
- struct Destructors {
- sqlite3_destructor_type string_destructor = sqlite_utils::kSqliteTransient;
- sqlite3_destructor_type bytes_destructor = sqlite_utils::kSqliteTransient;
- };
-
- // The function which will be exectued with the arguments from SQL.
- //
- // Implementations MUST define this function themselves; this function is
- // declared but *not* defined so linker errors will be thrown if not defined.
- //
- // |ctx|: the context object passed at registration time.
- // |argc|: number of arguments.
- // |argv|: arguments to the function.
- // |out|: the return value of the function.
- // |destructors|: destructors for string/bytes return values.
- static base::Status Run(Context* ctx,
- size_t argc,
- sqlite3_value** argv,
- SqlValue& out,
- Destructors& destructors);
-
- // Executed after the result from |Run| is reported to SQLite.
- // Allows implementations to verify post-conditions without needing to worry
- // about overwriting return types.
- //
- // Implementations do not need to define this function; a default no-op
- // implementation will be used in this case.
- static base::Status VerifyPostConditions(Context*);
-
- // Executed after the result from |Run| is reported to SQLite.
- // Allows any pending state to be cleaned up post-copy of results by SQLite:
- // this function will be called even if |Run| or |PostRun| returned errors.
- //
- // Implementations do not need to define this function; a default no-op
- // implementation will be used in this case.
- static void Cleanup(Context*);
-};
-
-// Registers a C++ function to be runnable from SQL.
-// The format of the function is given by the |SqlFunction|; see the
-// documentaion above.
-//
-// |db|: sqlite3 database object
-// |name|: name of the function in SQL
-// |argc|: number of arguments for this function, -1 if variable
-// |ctx|: context object for the function (see SqlFunction::Run above);
-// this object *must* outlive the function so should likely be
-// either static or scoped to the lifetime of TraceProcessor.
-// |determistic|: whether this function has deterministic output given the
-// same set of arguments.
-template <typename Function>
-base::Status RegisterSqlFunction(sqlite3* db,
- const char* name,
- int argc,
- typename Function::Context* ctx,
- bool deterministic = true);
-
-// Same as above except allows a unique_ptr to be passed for the context; this
-// allows for SQLite to manage the lifetime of this pointer instead of the
-// essentially static requirement of the context pointer above.
-template <typename Function>
-base::Status RegisterSqlFunction(
- sqlite3* db,
- const char* name,
- int argc,
- std::unique_ptr<typename Function::Context> ctx,
- bool deterministic = true);
-
-} // namespace trace_processor
-} // namespace perfetto
-
-// The rest of this file is just implementation details which we need
-// in the header file because it is templated code. We separate it out
-// like this to keep the API people actually care about easy to read.
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace sqlite_internal {
-
-// RAII type to call Function::Cleanup when destroyed.
-template <typename Function>
-struct ScopedCleanup {
- typename Function::Context* ctx;
- ~ScopedCleanup() { Function::Cleanup(ctx); }
-};
-
-template <typename Function>
-void WrapSqlFunction(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
- using Context = typename Function::Context;
- Context* ud = static_cast<Context*>(sqlite3_user_data(ctx));
-
- ScopedCleanup<Function> scoped_cleanup{ud};
- SqlValue value{};
- SqlFunction::Destructors destructors{};
- base::Status status =
- Function::Run(ud, static_cast<size_t>(argc), argv, value, destructors);
- if (!status.ok()) {
- sqlite3_result_error(ctx, status.c_message(), -1);
- return;
- }
-
- if (Function::kVoidReturn) {
- if (!value.is_null()) {
- sqlite3_result_error(ctx, "void SQL function returned value", -1);
- return;
- }
-
- // If the function doesn't want to return anything, set the "VOID"
- // pointer type to a non-null value. Note that because of the weird
- // way |sqlite3_value_pointer| works, we need to set some value even
- // if we don't actually read it - just set it to a pointer to an empty
- // string for this reason.
- static char kVoidValue[] = "";
- sqlite3_result_pointer(ctx, kVoidValue, "VOID", nullptr);
- } else {
- sqlite_utils::ReportSqlValue(ctx, value, destructors.string_destructor,
- destructors.bytes_destructor);
- }
-
- status = Function::VerifyPostConditions(ud);
- if (!status.ok()) {
- sqlite3_result_error(ctx, status.c_message(), -1);
- return;
- }
-}
-} // namespace sqlite_internal
-
-template <typename Function>
-base::Status RegisterSqlFunction(sqlite3* db,
- const char* name,
- int argc,
- typename Function::Context* ctx,
- bool deterministic) {
- int flags = SQLITE_UTF8 | (deterministic ? SQLITE_DETERMINISTIC : 0);
- int ret = sqlite3_create_function_v2(
- db, name, static_cast<int>(argc), flags, ctx,
- sqlite_internal::WrapSqlFunction<Function>, nullptr, nullptr, nullptr);
- if (ret != SQLITE_OK) {
- return base::ErrStatus("Unable to register function with name %s", name);
- }
- return base::OkStatus();
-}
-
-template <typename Function>
-base::Status RegisterSqlFunction(
- sqlite3* db,
- const char* name,
- int argc,
- std::unique_ptr<typename Function::Context> user_data,
- bool deterministic) {
- int flags = SQLITE_UTF8 | (deterministic ? SQLITE_DETERMINISTIC : 0);
- int ret = sqlite3_create_function_v2(
- db, name, static_cast<int>(argc), flags, user_data.release(),
- sqlite_internal::WrapSqlFunction<Function>, nullptr, nullptr,
- [](void* ptr) { delete static_cast<typename Function::Context*>(ptr); });
- if (ret != SQLITE_OK) {
- return base::ErrStatus("Unable to register function with name %s", name);
- }
- return base::OkStatus();
-}
-
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_PRELUDE_FUNCTIONS_REGISTER_FUNCTION_H_
diff --git a/src/trace_processor/prelude/functions/register_function.cc b/src/trace_processor/prelude/functions/sql_function.cc
similarity index 80%
rename from src/trace_processor/prelude/functions/register_function.cc
rename to src/trace_processor/prelude/functions/sql_function.cc
index ef41f1d..26bac5e 100644
--- a/src/trace_processor/prelude/functions/register_function.cc
+++ b/src/trace_processor/prelude/functions/sql_function.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open 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,9 +14,7 @@
* limitations under the License.
*/
-#include "src/trace_processor/prelude/functions/register_function.h"
-#include "sqlite3.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
namespace perfetto {
namespace trace_processor {
diff --git a/src/trace_processor/prelude/functions/sql_function.h b/src/trace_processor/prelude/functions/sql_function.h
new file mode 100644
index 0000000..ba7fab7
--- /dev/null
+++ b/src/trace_processor/prelude/functions/sql_function.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_PRELUDE_FUNCTIONS_SQL_FUNCTION_H_
+#define SRC_TRACE_PROCESSOR_PRELUDE_FUNCTIONS_SQL_FUNCTION_H_
+
+#include <sqlite3.h>
+#include <memory>
+
+#include "perfetto/base/status.h"
+#include "perfetto/trace_processor/basic_types.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Prototype for a C++ function which can be registered with SQLite.
+//
+// Usage
+//
+// Define a subclass of this struct as follows:
+// struct YourFunction : public SqlFunction {
+// // Optional if you want a custom context object (i.e. an object
+// // passed in at registration time which will be passed to Run on
+// // every invocation)
+// struct YourContext { /* define context fields here */ };
+//
+// static base::Status Run(/* see parameters below */) {
+// /* function body here */
+// }
+//
+// static base::Status Cleanup(/* see parameters below */) {
+// /* function body here */
+// }
+// }
+//
+// Then, register this function with SQLite using RegisterFunction (see below);
+// you'll likely want to do this in TraceProcessorImpl:
+// RegisterFunction<YourFunction>(/* see arguments below */)
+struct SqlFunction {
+ // The type of the context object which will be passed to the function.
+ // Can be redefined in any sub-classes to override the context.
+ using Context = void;
+
+ // Indicates whether this function is "void" (i.e. doesn't actually want
+ // to return a value). While the function will still return null in SQL
+ // (because SQLite does not actually allow null functions), for accounting
+ // purposes, this null will be ignored when verifying whether this statement
+ // has any output.
+ // Can be redefined in any sub-classes to override it.
+ // If this is set to true, subclasses must not modify |out| or |destructors|.
+ static constexpr bool kVoidReturn = false;
+
+ // Struct which holds destructors for strings/bytes returned from the
+ // function. Passed as an argument to |Run| to allow implementations to
+ // override the destructors.
+ struct Destructors {
+ // This matches SQLITE_TRANSIENT constant which we cannot use because it
+ // expands to a C-style cast, causing compiler warnings.
+ sqlite3_destructor_type string_destructor =
+ reinterpret_cast<sqlite3_destructor_type>(-1);
+ sqlite3_destructor_type bytes_destructor =
+ reinterpret_cast<sqlite3_destructor_type>(-1);
+ };
+
+ // The function which will be executed with the arguments from SQL.
+ //
+ // Implementations MUST define this function themselves; this function is
+ // declared but *not* defined so linker errors will be thrown if not defined.
+ //
+ // |ctx|: the context object passed at registration time.
+ // |argc|: number of arguments.
+ // |argv|: arguments to the function.
+ // |out|: the return value of the function.
+ // |destructors|: destructors for string/bytes return values.
+ static base::Status Run(Context* ctx,
+ size_t argc,
+ sqlite3_value** argv,
+ SqlValue& out,
+ Destructors& destructors);
+
+ // Executed after the result from |Run| is reported to SQLite.
+ // Allows implementations to verify post-conditions without needing to worry
+ // about overwriting return types.
+ //
+ // Implementations do not need to define this function; a default no-op
+ // implementation will be used in this case.
+ static base::Status VerifyPostConditions(Context*);
+
+ // Executed after the result from |Run| is reported to SQLite.
+ // Allows any pending state to be cleaned up post-copy of results by SQLite:
+ // this function will be called even if |Run| or |PostRun| returned errors.
+ //
+ // Implementations do not need to define this function; a default no-op
+ // implementation will be used in this case.
+ static void Cleanup(Context*);
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_PRELUDE_FUNCTIONS_SQL_FUNCTION_H_
diff --git a/src/trace_processor/prelude/functions/stack_functions.cc b/src/trace_processor/prelude/functions/stack_functions.cc
index 2f8730b..e2c4468 100644
--- a/src/trace_processor/prelude/functions/stack_functions.cc
+++ b/src/trace_processor/prelude/functions/stack_functions.cc
@@ -31,7 +31,8 @@
#include "perfetto/trace_processor/basic_types.h"
#include "perfetto/trace_processor/status.h"
#include "protos/perfetto/trace_processor/stack.pbzero.h"
-#include "src/trace_processor/prelude/functions/register_function.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
+#include "src/trace_processor/sqlite/sqlite_engine.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
@@ -243,15 +244,16 @@
} // namespace
-base::Status RegisterStackFunctions(sqlite3* db,
+base::Status RegisterStackFunctions(SqliteEngine* engine,
TraceProcessorContext* context) {
- RETURN_IF_ERROR(RegisterSqlFunction<CatStacksFunction>(
- db, CatStacksFunction::kFunctionName, -1, context->storage.get()));
- RETURN_IF_ERROR(RegisterSqlFunction<StackFromStackProfileFrameFunction>(
- db, StackFromStackProfileFrameFunction::kFunctionName, 1,
- context->storage.get()));
- return RegisterSqlFunction<StackFromStackProfileCallsiteFunction>(
- db, StackFromStackProfileCallsiteFunction::kFunctionName, -1,
+ RETURN_IF_ERROR(engine->RegisterSqlFunction<CatStacksFunction>(
+ CatStacksFunction::kFunctionName, -1, context->storage.get()));
+ RETURN_IF_ERROR(
+ engine->RegisterSqlFunction<StackFromStackProfileFrameFunction>(
+ StackFromStackProfileFrameFunction::kFunctionName, 1,
+ context->storage.get()));
+ return engine->RegisterSqlFunction<StackFromStackProfileCallsiteFunction>(
+ StackFromStackProfileCallsiteFunction::kFunctionName, -1,
context->storage.get());
}
diff --git a/src/trace_processor/prelude/functions/stack_functions.h b/src/trace_processor/prelude/functions/stack_functions.h
index 5acb046..7fd676c 100644
--- a/src/trace_processor/prelude/functions/stack_functions.h
+++ b/src/trace_processor/prelude/functions/stack_functions.h
@@ -26,6 +26,7 @@
namespace perfetto {
namespace trace_processor {
+class SqliteEngine;
class TraceProcessorContext;
// Registers the stack manipulation related functions:
@@ -49,7 +50,7 @@
// it generates a fake Frame
//
// See protos/perfetto/trace_processor/stack.proto
-base::Status RegisterStackFunctions(sqlite3* db,
+base::Status RegisterStackFunctions(SqliteEngine* engine,
TraceProcessorContext* context);
} // namespace trace_processor
diff --git a/src/trace_processor/prelude/functions/to_ftrace.h b/src/trace_processor/prelude/functions/to_ftrace.h
index c32ed79..9c55067 100644
--- a/src/trace_processor/prelude/functions/to_ftrace.h
+++ b/src/trace_processor/prelude/functions/to_ftrace.h
@@ -19,7 +19,7 @@
#include "perfetto/ext/base/flat_hash_map.h"
#include "perfetto/ext/base/string_writer.h"
-#include "src/trace_processor/prelude/functions/register_function.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
diff --git a/src/trace_processor/prelude/functions/utils.h b/src/trace_processor/prelude/functions/utils.h
index 82b293f..ac848d0 100644
--- a/src/trace_processor/prelude/functions/utils.h
+++ b/src/trace_processor/prelude/functions/utils.h
@@ -19,6 +19,7 @@
#include <sqlite3.h>
#include <unordered_map>
+
#include "perfetto/ext/base/base64.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/trace_processor/demangle.h"
@@ -26,10 +27,10 @@
#include "src/trace_processor/export_json.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/prelude/functions/create_function_internal.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
+#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/util/status_macros.h"
-#include "src/trace_processor/prelude/functions/register_function.h"
-
namespace perfetto {
namespace trace_processor {
diff --git a/src/trace_processor/prelude/functions/window_functions.h b/src/trace_processor/prelude/functions/window_functions.h
index 3a76fce..a3fbeaf 100644
--- a/src/trace_processor/prelude/functions/window_functions.h
+++ b/src/trace_processor/prelude/functions/window_functions.h
@@ -28,7 +28,7 @@
#include "src/trace_processor/prelude/functions/create_function_internal.h"
#include "src/trace_processor/util/status_macros.h"
-#include "src/trace_processor/prelude/functions/register_function.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
namespace perfetto {
namespace trace_processor {
diff --git a/src/trace_processor/prelude/operators/BUILD.gn b/src/trace_processor/prelude/operators/BUILD.gn
index 2a3daa6..3d994a7 100644
--- a/src/trace_processor/prelude/operators/BUILD.gn
+++ b/src/trace_processor/prelude/operators/BUILD.gn
@@ -42,5 +42,6 @@
"../../../../gn:default_deps",
"../../../../gn:gtest_and_gmock",
"../../../../gn:sqlite",
+ "../../sqlite",
]
}
diff --git a/src/trace_processor/prelude/operators/span_join_operator.cc b/src/trace_processor/prelude/operators/span_join_operator.cc
index 77ee7c8..2ee2839 100644
--- a/src/trace_processor/prelude/operators/span_join_operator.cc
+++ b/src/trace_processor/prelude/operators/span_join_operator.cc
@@ -24,6 +24,7 @@
#include <utility>
#include "perfetto/base/logging.h"
+#include "perfetto/base/status.h"
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/string_view.h"
@@ -105,20 +106,9 @@
} // namespace
-SpanJoinOperatorTable::SpanJoinOperatorTable(sqlite3* db, const TraceStorage*)
+SpanJoinOperatorTable::SpanJoinOperatorTable(sqlite3* db, const void*)
: db_(db) {}
-
-void SpanJoinOperatorTable::RegisterTable(sqlite3* db,
- const TraceStorage* storage) {
- RegistrationFlags flags;
- flags.type = RegistrationFlags::kExplicitCreateStateless;
-
- SqliteTable::Register<SpanJoinOperatorTable>(db, storage, "span_join", flags);
- SqliteTable::Register<SpanJoinOperatorTable>(db, storage, "span_left_join",
- flags);
- SqliteTable::Register<SpanJoinOperatorTable>(db, storage, "span_outer_join",
- flags);
-}
+SpanJoinOperatorTable::~SpanJoinOperatorTable() = default;
util::Status SpanJoinOperatorTable::Init(int argc,
const char* const* argv,
@@ -238,7 +228,7 @@
}
}
-std::unique_ptr<SqliteTable::Cursor> SpanJoinOperatorTable::CreateCursor() {
+std::unique_ptr<SqliteTable::BaseCursor> SpanJoinOperatorTable::CreateCursor() {
return std::unique_ptr<SpanJoinOperatorTable::Cursor>(new Cursor(this, db_));
}
@@ -403,14 +393,15 @@
}
SpanJoinOperatorTable::Cursor::Cursor(SpanJoinOperatorTable* table, sqlite3* db)
- : SqliteTable::Cursor(table),
+ : SqliteTable::BaseCursor(table),
t1_(table, &table->t1_defn_, db),
t2_(table, &table->t2_defn_, db),
table_(table) {}
+SpanJoinOperatorTable::Cursor::~Cursor() = default;
-base::Status SpanJoinOperatorTable::Cursor::FilterInner(
- const QueryConstraints& qc,
- sqlite3_value** argv) {
+base::Status SpanJoinOperatorTable::Cursor::Filter(const QueryConstraints& qc,
+ sqlite3_value** argv,
+ FilterHistory) {
PERFETTO_TP_TRACE(metatrace::Category::QUERY, "SPAN_JOIN_XFILTER");
bool t1_partitioned_mixed =
@@ -432,7 +423,7 @@
return FindOverlappingSpan();
}
-base::Status SpanJoinOperatorTable::Cursor::NextInner() {
+base::Status SpanJoinOperatorTable::Cursor::Next() {
RETURN_IF_ERROR(next_query_->Next());
return FindOverlappingSpan();
}
@@ -553,11 +544,12 @@
return t1_less ? &t1_ : &t2_;
}
-int SpanJoinOperatorTable::Cursor::Eof() {
+bool SpanJoinOperatorTable::Cursor::Eof() {
return t1_.IsEof() || t2_.IsEof();
}
-int SpanJoinOperatorTable::Cursor::Column(sqlite3_context* context, int N) {
+base::Status SpanJoinOperatorTable::Cursor::Column(sqlite3_context* context,
+ int N) {
PERFETTO_DCHECK(t1_.IsReal() || t2_.IsReal());
switch (N) {
@@ -595,7 +587,7 @@
t2_.ReportSqliteResult(context, locator.col_index);
}
}
- return SQLITE_OK;
+ return base::OkStatus();
}
SpanJoinOperatorTable::Query::Query(SpanJoinOperatorTable* table,
diff --git a/src/trace_processor/prelude/operators/span_join_operator.h b/src/trace_processor/prelude/operators/span_join_operator.h
index f150a75..3f7a006 100644
--- a/src/trace_processor/prelude/operators/span_join_operator.h
+++ b/src/trace_processor/prelude/operators/span_join_operator.h
@@ -69,7 +69,8 @@
//
// All other columns apart from timestamp (ts), duration (dur) and the join key
// are passed through unchanged.
-class SpanJoinOperatorTable : public SqliteTable {
+class SpanJoinOperatorTable final
+ : public TypedSqliteTable<SpanJoinOperatorTable, const void*> {
public:
// Enum indicating whether the queries on the two inner tables should
// emit shadows.
@@ -316,32 +317,17 @@
};
// Base class for a cursor on the span table.
- class Cursor : public SqliteTable::Cursor {
+ class Cursor final : public SqliteTable::BaseCursor {
public:
Cursor(SpanJoinOperatorTable*, sqlite3* db);
- ~Cursor() override = default;
+ ~Cursor() final;
- int Filter(const QueryConstraints& qc,
- sqlite3_value** argv,
- FilterHistory) override {
- base::Status status = FilterInner(qc, argv);
- if (!status.ok()) {
- table_->SetErrorMessage(sqlite3_mprintf("%s", status.c_message()));
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
- }
- int Next() override {
- base::Status status = NextInner();
- if (!status.ok()) {
- table_->SetErrorMessage(sqlite3_mprintf("%s", status.c_message()));
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
- }
-
- int Column(sqlite3_context* context, int N) override;
- int Eof() override;
+ base::Status Filter(const QueryConstraints& qc,
+ sqlite3_value** argv,
+ FilterHistory);
+ base::Status Next();
+ base::Status Column(sqlite3_context* context, int N);
+ bool Eof();
private:
Cursor(Cursor&) = delete;
@@ -351,11 +337,7 @@
Cursor& operator=(Cursor&&) = default;
bool IsOverlappingSpan();
-
- base::Status NextInner();
- base::Status FilterInner(const QueryConstraints& qc, sqlite3_value** argv);
util::Status FindOverlappingSpan();
-
Query* FindEarliestFinishQuery();
Query t1_;
@@ -369,15 +351,14 @@
SpanJoinOperatorTable* table_;
};
- SpanJoinOperatorTable(sqlite3*, const TraceStorage*);
-
- static void RegisterTable(sqlite3* db, const TraceStorage* storage);
+ SpanJoinOperatorTable(sqlite3*, const void*);
+ ~SpanJoinOperatorTable() final;
// Table implementation.
- util::Status Init(int, const char* const*, SqliteTable::Schema*) override;
- std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
- int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) override;
- int FindFunction(const char* name, FindFunctionFn* fn, void** args) override;
+ util::Status Init(int, const char* const*, SqliteTable::Schema*) final;
+ std::unique_ptr<SqliteTable::BaseCursor> CreateCursor() final;
+ int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) final;
+ int FindFunction(const char* name, FindFunctionFn* fn, void** args) final;
private:
// Columns of the span operator table.
diff --git a/src/trace_processor/prelude/operators/span_join_operator_unittest.cc b/src/trace_processor/prelude/operators/span_join_operator_unittest.cc
index 737e828..661a7f1 100644
--- a/src/trace_processor/prelude/operators/span_join_operator_unittest.cc
+++ b/src/trace_processor/prelude/operators/span_join_operator_unittest.cc
@@ -16,6 +16,7 @@
#include "src/trace_processor/prelude/operators/span_join_operator.h"
+#include "src/trace_processor/sqlite/sqlite_engine.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
@@ -25,19 +26,19 @@
class SpanJoinOperatorTableTest : public ::testing::Test {
public:
SpanJoinOperatorTableTest() {
- sqlite3* db = nullptr;
- PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
- PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
- db_.reset(db);
-
- SpanJoinOperatorTable::RegisterTable(db_.get(), nullptr);
+ engine_.RegisterVirtualTableModule<SpanJoinOperatorTable>(
+ "span_join", nullptr, SqliteTable::TableType::kExplicitCreate, false);
+ engine_.RegisterVirtualTableModule<SpanJoinOperatorTable>(
+ "span_left_join", nullptr, SqliteTable::TableType::kExplicitCreate,
+ false);
}
void PrepareValidStatement(const std::string& sql) {
int size = static_cast<int>(sql.size());
sqlite3_stmt* stmt;
- ASSERT_EQ(sqlite3_prepare_v2(*db_, sql.c_str(), size, &stmt, nullptr),
- SQLITE_OK);
+ ASSERT_EQ(
+ sqlite3_prepare_v2(engine_.db(), sql.c_str(), size, &stmt, nullptr),
+ SQLITE_OK);
stmt_.reset(stmt);
}
@@ -55,7 +56,7 @@
}
protected:
- ScopedDb db_;
+ SqliteEngine engine_;
ScopedStmt stmt_;
};
diff --git a/src/trace_processor/prelude/operators/window_operator.cc b/src/trace_processor/prelude/operators/window_operator.cc
index c5e9b73..68f2ff4 100644
--- a/src/trace_processor/prelude/operators/window_operator.cc
+++ b/src/trace_processor/prelude/operators/window_operator.cc
@@ -16,6 +16,7 @@
#include "src/trace_processor/prelude/operators/window_operator.h"
+#include "perfetto/base/status.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
namespace perfetto {
@@ -26,15 +27,7 @@
} // namespace
WindowOperatorTable::WindowOperatorTable(sqlite3*, const TraceStorage*) {}
-
-void WindowOperatorTable::RegisterTable(sqlite3* db,
- const TraceStorage* storage) {
- RegistrationFlags flags;
- flags.writable = true;
- flags.type = RegistrationFlags::kEponymous;
-
- SqliteTable::Register<WindowOperatorTable>(db, storage, "window", flags);
-}
+WindowOperatorTable::~WindowOperatorTable() = default;
base::Status WindowOperatorTable::Init(int,
const char* const*,
@@ -61,54 +54,55 @@
return base::OkStatus();
}
-std::unique_ptr<SqliteTable::Cursor> WindowOperatorTable::CreateCursor() {
- return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
+std::unique_ptr<SqliteTable::BaseCursor> WindowOperatorTable::CreateCursor() {
+ return std::unique_ptr<SqliteTable::BaseCursor>(new Cursor(this));
}
int WindowOperatorTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
return SQLITE_OK;
}
-int WindowOperatorTable::ModifyConstraints(QueryConstraints* qc) {
+base::Status WindowOperatorTable::ModifyConstraints(QueryConstraints* qc) {
// Remove ordering on timestamp if it is the only ordering as we are already
// sorted on TS. This makes span joining significantly faster.
const auto& ob = qc->order_by();
if (ob.size() == 1 && ob[0].iColumn == Column::kTs && !ob[0].desc) {
qc->mutable_order_by()->clear();
}
- return SQLITE_OK;
+ return base::OkStatus();
}
-int WindowOperatorTable::Update(int argc,
- sqlite3_value** argv,
- sqlite3_int64*) {
+base::Status WindowOperatorTable::Update(int argc,
+ sqlite3_value** argv,
+ sqlite3_int64*) {
// We only support updates to ts and dur. Disallow deletes (argc == 1) and
// inserts (argv[0] == null).
- if (argc < 2 || sqlite3_value_type(argv[0]) == SQLITE_NULL)
- return SQLITE_READONLY;
+ if (argc < 2 || sqlite3_value_type(argv[0]) == SQLITE_NULL) {
+ return base::ErrStatus(
+ "Invalid number/value of arguments when updating window table");
+ }
int64_t new_quantum = sqlite3_value_int64(argv[3]);
int64_t new_start = sqlite3_value_int64(argv[4]);
int64_t new_dur = sqlite3_value_int64(argv[5]);
if (new_dur == 0) {
- auto* err = sqlite3_mprintf("Cannot set duration of window table to zero.");
- SetErrorMessage(err);
- return SQLITE_ERROR;
+ return base::ErrStatus("Cannot set duration of window table to zero.");
}
quantum_ = new_quantum;
window_start_ = new_start;
window_dur_ = new_dur;
- return SQLITE_OK;
+ return base::OkStatus();
}
WindowOperatorTable::Cursor::Cursor(WindowOperatorTable* table)
- : SqliteTable::Cursor(table), table_(table) {}
+ : SqliteTable::BaseCursor(table), table_(table) {}
+WindowOperatorTable::Cursor::~Cursor() = default;
-int WindowOperatorTable::Cursor::Filter(const QueryConstraints& qc,
- sqlite3_value** argv,
- FilterHistory) {
+base::Status WindowOperatorTable::Cursor::Filter(const QueryConstraints& qc,
+ sqlite3_value** argv,
+ FilterHistory) {
*this = Cursor(table_);
window_start_ = table_->window_start_;
window_end_ = table_->window_start_ + table_->window_dur_;
@@ -127,10 +121,11 @@
} else {
filter_type_ = FilterType::kReturnAll;
}
- return SQLITE_OK;
+ return base::OkStatus();
}
-int WindowOperatorTable::Cursor::Column(sqlite3_context* context, int N) {
+base::Status WindowOperatorTable::Cursor::Column(sqlite3_context* context,
+ int N) {
switch (N) {
case Column::kQuantum: {
sqlite3_result_int64(context,
@@ -167,10 +162,10 @@
break;
}
}
- return SQLITE_OK;
+ return base::OkStatus();
}
-int WindowOperatorTable::Cursor::Next() {
+base::Status WindowOperatorTable::Cursor::Next() {
switch (filter_type_) {
case FilterType::kReturnFirst:
current_ts_ = window_end_;
@@ -181,10 +176,10 @@
break;
}
row_id_++;
- return SQLITE_OK;
+ return base::OkStatus();
}
-int WindowOperatorTable::Cursor::Eof() {
+bool WindowOperatorTable::Cursor::Eof() {
return current_ts_ >= window_end_;
}
diff --git a/src/trace_processor/prelude/operators/window_operator.h b/src/trace_processor/prelude/operators/window_operator.h
index d10b81b..5f4af16 100644
--- a/src/trace_processor/prelude/operators/window_operator.h
+++ b/src/trace_processor/prelude/operators/window_operator.h
@@ -20,6 +20,7 @@
#include <limits>
#include <memory>
+#include "perfetto/base/status.h"
#include "src/trace_processor/sqlite/sqlite_table.h"
namespace perfetto {
@@ -27,7 +28,8 @@
class TraceStorage;
-class WindowOperatorTable : public SqliteTable {
+class WindowOperatorTable final
+ : public TypedSqliteTable<WindowOperatorTable, const TraceStorage*> {
public:
enum Column {
kRowId = 0,
@@ -38,17 +40,21 @@
kDuration = 5,
kQuantumTs = 6
};
- class Cursor : public SqliteTable::Cursor {
+ class Cursor final : public SqliteTable::BaseCursor {
public:
explicit Cursor(WindowOperatorTable*);
+ ~Cursor() final;
+
+ Cursor(Cursor&&) = default;
+ Cursor& operator=(Cursor&&) = default;
// Implementation of SqliteTable::Cursor.
- int Filter(const QueryConstraints& qc,
- sqlite3_value**,
- FilterHistory) override;
- int Next() override;
- int Eof() override;
- int Column(sqlite3_context*, int N) override;
+ base::Status Filter(const QueryConstraints& qc,
+ sqlite3_value**,
+ FilterHistory);
+ base::Status Next();
+ bool Eof();
+ base::Status Column(sqlite3_context*, int N);
private:
// Defines the data to be generated by the table.
@@ -72,16 +78,15 @@
WindowOperatorTable* table_ = nullptr;
};
- static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
WindowOperatorTable(sqlite3*, const TraceStorage*);
+ ~WindowOperatorTable() final;
// Table implementation.
- base::Status Init(int, const char* const*, Schema* schema) override;
- std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
- int ModifyConstraints(QueryConstraints* qc) override;
- int Update(int, sqlite3_value**, sqlite3_int64*) override;
+ base::Status Init(int, const char* const*, Schema* schema) final;
+ std::unique_ptr<SqliteTable::BaseCursor> CreateCursor() final;
+ int BestIndex(const QueryConstraints&, BestIndexInfo*) final;
+ base::Status ModifyConstraints(QueryConstraints* qc) final;
+ base::Status Update(int, sqlite3_value**, sqlite3_int64*) final;
private:
int64_t quantum_ = 0;
@@ -91,6 +96,7 @@
// uint64s.
int64_t window_dur_ = std::numeric_limits<int64_t>::max();
};
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/prelude/table_functions/BUILD.gn b/src/trace_processor/prelude/table_functions/BUILD.gn
index 1125c22..2a97bca 100644
--- a/src/trace_processor/prelude/table_functions/BUILD.gn
+++ b/src/trace_processor/prelude/table_functions/BUILD.gn
@@ -39,8 +39,6 @@
"experimental_slice_layout.h",
"flamegraph_construction_algorithms.cc",
"flamegraph_construction_algorithms.h",
- "table_function.cc",
- "table_function.h",
"view.cc",
"view.h",
]
@@ -53,12 +51,26 @@
"../../db",
"../../importers/proto:full",
"../../importers/proto:minimal",
- "../../sqlite:sqlite_minimal",
+ "../../sqlite",
"../../storage",
"../../tables",
"../../types",
"../../util",
]
+ public_deps = [ ":interface" ]
+}
+
+source_set("interface") {
+ sources = [
+ "table_function.cc",
+ "table_function.h",
+ ]
+ deps = [
+ "../../../../gn:default_deps",
+ "../../../base",
+ "../../db",
+ "../../sqlite:query_constraints",
+ ]
}
perfetto_tp_tables("tables") {
diff --git a/src/trace_processor/prelude/tables_views/tables.sql b/src/trace_processor/prelude/tables_views/tables.sql
index 1b7d016..28ea0f5 100644
--- a/src/trace_processor/prelude/tables_views/tables.sql
+++ b/src/trace_processor/prelude/tables_views/tables.sql
@@ -20,4 +20,6 @@
ts BIGINT,
dur BIGINT,
depth BIGINT
-);
\ No newline at end of file
+);
+
+CREATE VIRTUAL TABLE window USING window();
diff --git a/src/trace_processor/read_trace_integrationtest.cc b/src/trace_processor/read_trace_integrationtest.cc
index 439f1fa..818eb6d 100644
--- a/src/trace_processor/read_trace_integrationtest.cc
+++ b/src/trace_processor/read_trace_integrationtest.cc
@@ -46,7 +46,23 @@
return raw_trace;
}
-TEST(ReadTraceIntegrationTest, CompressedTrace) {
+bool ZlibSupported() {
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+ return true;
+#else
+ return false;
+#endif
+}
+
+class ReadTraceIntegrationTest : public testing::Test {
+ void SetUp() override {
+ if (!ZlibSupported()) {
+ GTEST_SKIP() << "Gzip not enabled";
+ }
+ }
+};
+
+TEST_F(ReadTraceIntegrationTest, CompressedTrace) {
base::ScopedFstream f = OpenTestTrace("test/data/compressed.pb");
std::vector<uint8_t> raw_trace = ReadAllData(f);
@@ -68,7 +84,7 @@
ASSERT_EQ(packet_count, 2412u);
}
-TEST(ReadTraceIntegrationTest, NonProtobufShouldNotDecompress) {
+TEST_F(ReadTraceIntegrationTest, NonProtobufShouldNotDecompress) {
base::ScopedFstream f = OpenTestTrace("test/data/unsorted_trace.json");
std::vector<uint8_t> raw_trace = ReadAllData(f);
@@ -78,7 +94,7 @@
ASSERT_FALSE(status.ok());
}
-TEST(ReadTraceIntegrationTest, OuterGzipDecompressTrace) {
+TEST_F(ReadTraceIntegrationTest, OuterGzipDecompressTrace) {
base::ScopedFstream f =
OpenTestTrace("test/data/example_android_trace_30s.pb.gz");
std::vector<uint8_t> raw_compressed_trace = ReadAllData(f);
@@ -96,7 +112,7 @@
ASSERT_EQ(decompressed, raw_trace);
}
-TEST(ReadTraceIntegrationTest, DoubleGzipDecompressTrace) {
+TEST_F(ReadTraceIntegrationTest, DoubleGzipDecompressTrace) {
base::ScopedFstream f = OpenTestTrace("test/data/compressed.pb.gz");
std::vector<uint8_t> raw_compressed_trace = ReadAllData(f);
diff --git a/src/trace_processor/sqlite/BUILD.gn b/src/trace_processor/sqlite/BUILD.gn
index 25024b1..7045815 100644
--- a/src/trace_processor/sqlite/BUILD.gn
+++ b/src/trace_processor/sqlite/BUILD.gn
@@ -21,48 +21,48 @@
"db_sqlite_table.cc",
"db_sqlite_table.h",
"query_cache.h",
+ "scoped_db.h",
"sql_stats_table.cc",
"sql_stats_table.h",
"sqlite_engine.cc",
"sqlite_engine.h",
+ "sqlite_table.cc",
+ "sqlite_table.h",
"sqlite_utils.cc",
"sqlite_utils.h",
+ "sqlite_utils.h",
"stats_table.cc",
"stats_table.h",
]
deps = [
+ ":query_constraints",
"..:metatrace",
"../../../gn:default_deps",
"../../../gn:sqlite",
+ "../../../include/perfetto/trace_processor",
"../../../protos/perfetto/trace/ftrace:zero",
"../../base",
"../containers",
"../db",
"../importers/common",
"../importers/ftrace:ftrace_descriptors",
- "../prelude/table_functions",
+ "../prelude/functions:interface",
+ "../prelude/table_functions:interface",
"../storage",
"../types",
"../util",
"../util:profile_builder",
]
- public_deps = [ ":sqlite_minimal" ]
}
-source_set("sqlite_minimal") {
+source_set("query_constraints") {
sources = [
"query_constraints.cc",
"query_constraints.h",
- "scoped_db.h",
- "sqlite_table.cc",
- "sqlite_table.h",
- "sqlite_utils.h",
]
deps = [
- "..:metatrace",
"../../../gn:default_deps",
"../../../gn:sqlite",
- "../../../include/perfetto/trace_processor",
"../../base",
]
}
@@ -75,8 +75,8 @@
"sqlite_utils_unittest.cc",
]
deps = [
+ ":query_constraints",
":sqlite",
- ":sqlite_minimal",
"../../../gn:default_deps",
"../../../gn:gtest_and_gmock",
"../../../gn:sqlite",
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index 31cbed1..f73c5c1 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -16,6 +16,7 @@
#include "src/trace_processor/sqlite/db_sqlite_table.h"
+#include "perfetto/base/status.h"
#include "perfetto/ext/base/small_vector.h"
#include "perfetto/ext/base/string_writer.h"
#include "src/trace_processor/containers/bit_vector.h"
@@ -134,32 +135,6 @@
generator_(std::move(context.generator)) {}
DbSqliteTable::~DbSqliteTable() = default;
-void DbSqliteTable::RegisterTable(sqlite3* db,
- QueryCache* cache,
- const Table* table,
- const std::string& name) {
- Context context{cache, TableComputation::kStatic, table, nullptr};
- SqliteTable::Register<DbSqliteTable, Context>(db, std::move(context), name,
- RegistrationFlags{});
-}
-
-void DbSqliteTable::RegisterTable(sqlite3* db,
- QueryCache* cache,
- std::unique_ptr<TableFunction> generator) {
- // Figure out if the table needs explicit args (in the form of constraints
- // on hidden columns) passed to it in order to make the query valid.
- base::Status status = generator->ValidateConstraints(
- QueryConstraints(std::numeric_limits<uint64_t>::max()));
-
- std::string table_name = generator->TableName();
- Context context{cache, TableComputation::kDynamic, nullptr,
- std::move(generator)};
- RegistrationFlags flags;
- flags.requires_hidden_constraints = !status.ok();
- SqliteTable::Register<DbSqliteTable, Context>(db, std::move(context),
- table_name, flags);
-}
-
base::Status DbSqliteTable::Init(int, const char* const*, Schema* schema) {
switch (computation_) {
case TableComputation::kStatic:
@@ -234,9 +209,9 @@
info->sqlite_omit_order_by = true;
}
-int DbSqliteTable::ModifyConstraints(QueryConstraints* qc) {
+base::Status DbSqliteTable::ModifyConstraints(QueryConstraints* qc) {
ModifyConstraints(schema_, qc);
- return SQLITE_OK;
+ return base::OkStatus();
}
void DbSqliteTable::ModifyConstraints(const Table::Schema& schema,
@@ -394,14 +369,15 @@
return QueryCost{final_cost, current_row_count};
}
-std::unique_ptr<SqliteTable::Cursor> DbSqliteTable::CreateCursor() {
+std::unique_ptr<SqliteTable::BaseCursor> DbSqliteTable::CreateCursor() {
return std::unique_ptr<Cursor>(new Cursor(this, cache_));
}
DbSqliteTable::Cursor::Cursor(DbSqliteTable* sqlite_table, QueryCache* cache)
- : SqliteTable::Cursor(sqlite_table),
+ : SqliteTable::BaseCursor(sqlite_table),
db_sqlite_table_(sqlite_table),
cache_(cache) {}
+DbSqliteTable::Cursor::~Cursor() = default;
void DbSqliteTable::Cursor::TryCacheCreateSortedTable(
const QueryConstraints& qc,
@@ -455,9 +431,9 @@
});
}
-int DbSqliteTable::Cursor::Filter(const QueryConstraints& qc,
- sqlite3_value** argv,
- FilterHistory history) {
+base::Status DbSqliteTable::Cursor::Filter(const QueryConstraints& qc,
+ sqlite3_value** argv,
+ FilterHistory history) {
// Clear out the iterator before filtering to ensure the destructor is run
// before the table's destructor.
iterator_ = std::nullopt;
@@ -513,10 +489,8 @@
constraints_, orders_, cols_used_bv, computed_table);
if (!status.ok()) {
- auto* sqlite_err = sqlite3_mprintf(
- "%s: %s", db_sqlite_table_->name().c_str(), status.c_message());
- db_sqlite_table_->SetErrorMessage(sqlite_err);
- return SQLITE_CONSTRAINT;
+ return base::ErrStatus("%s: %s", db_sqlite_table_->name().c_str(),
+ status.c_message());
}
PERFETTO_DCHECK(computed_table);
dynamic_table_ = std::move(computed_table);
@@ -633,25 +607,24 @@
eof_ = !*iterator_;
}
-
- return SQLITE_OK;
+ return base::OkStatus();
}
-int DbSqliteTable::Cursor::Next() {
+base::Status DbSqliteTable::Cursor::Next() {
if (mode_ == Mode::kSingleRow) {
eof_ = true;
} else {
iterator_->Next();
eof_ = !*iterator_;
}
- return SQLITE_OK;
+ return base::OkStatus();
}
-int DbSqliteTable::Cursor::Eof() {
+bool DbSqliteTable::Cursor::Eof() {
return eof_;
}
-int DbSqliteTable::Cursor::Column(sqlite3_context* ctx, int raw_col) {
+base::Status DbSqliteTable::Cursor::Column(sqlite3_context* ctx, int raw_col) {
uint32_t column = static_cast<uint32_t>(raw_col);
SqlValue value = mode_ == Mode::kSingleRow
? SourceTable()->GetColumn(column).Get(*single_row_)
@@ -665,7 +638,7 @@
// SQLite no longer cares about the bytes pointer.
sqlite_utils::ReportSqlValue(ctx, value, sqlite_utils::kSqliteStatic,
sqlite_utils::kSqliteStatic);
- return SQLITE_OK;
+ return base::OkStatus();
}
} // namespace trace_processor
diff --git a/src/trace_processor/sqlite/db_sqlite_table.h b/src/trace_processor/sqlite/db_sqlite_table.h
index 6a2282d..96a63e5 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.h
+++ b/src/trace_processor/sqlite/db_sqlite_table.h
@@ -17,6 +17,7 @@
#ifndef SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_
#define SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_
+#include "perfetto/base/status.h"
#include "src/trace_processor/containers/bit_vector.h"
#include "src/trace_processor/db/table.h"
#include "src/trace_processor/prelude/table_functions/table_function.h"
@@ -26,32 +27,48 @@
namespace perfetto {
namespace trace_processor {
+enum class DbSqliteTableComputation {
+ // Mode when the table is static (i.e. passed in at construction
+ // time).
+ kStatic,
+
+ // Mode when table is dynamically computed at filter time.
+ kDynamic,
+};
+
+struct DbSqliteTableContext {
+ QueryCache* cache;
+ DbSqliteTableComputation computation;
+
+ // Only valid when computation == TableComputation::kStatic.
+ const Table* static_table;
+
+ // Only valid when computation == TableComputation::kDynamic.
+ std::unique_ptr<TableFunction> generator;
+};
+
// Implements the SQLite table interface for db tables.
-class DbSqliteTable : public SqliteTable {
+class DbSqliteTable final
+ : public TypedSqliteTable<DbSqliteTable, DbSqliteTableContext> {
public:
- enum class TableComputation {
- // Mode when the table is static (i.e. passed in at construction
- // time).
- kStatic,
+ using TableComputation = DbSqliteTableComputation;
+ using Context = DbSqliteTableContext;
- // Mode when table is dynamically computed at filter time.
- kDynamic,
- };
-
- class Cursor : public SqliteTable::Cursor {
+ class Cursor final : public SqliteTable::BaseCursor {
public:
Cursor(DbSqliteTable*, QueryCache*);
+ ~Cursor() final;
Cursor(Cursor&&) noexcept = default;
Cursor& operator=(Cursor&&) = default;
// Implementation of SqliteTable::Cursor.
- int Filter(const QueryConstraints& qc,
- sqlite3_value** argv,
- FilterHistory) override;
- int Next() override;
- int Eof() override;
- int Column(sqlite3_context*, int N) override;
+ base::Status Filter(const QueryConstraints& qc,
+ sqlite3_value** argv,
+ FilterHistory);
+ base::Status Next();
+ bool Eof();
+ base::Status Column(sqlite3_context*, int N);
private:
enum class Mode {
@@ -108,36 +125,15 @@
double cost;
uint32_t rows;
};
- struct Context {
- QueryCache* cache;
- TableComputation computation;
-
- // Only valid when computation == TableComputation::kStatic.
- const Table* static_table;
-
- // Only valid when computation == TableComputation::kDynamic.
- std::unique_ptr<TableFunction> generator;
- };
-
- static void RegisterTable(sqlite3* db,
- QueryCache* cache,
- const Table* table,
- const std::string& name);
-
- static void RegisterTable(sqlite3* db,
- QueryCache* cache,
- std::unique_ptr<TableFunction> generator);
DbSqliteTable(sqlite3*, Context context);
- virtual ~DbSqliteTable() override;
+ virtual ~DbSqliteTable() final;
// Table implementation.
- base::Status Init(int,
- const char* const*,
- SqliteTable::Schema*) override final;
- std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
- int ModifyConstraints(QueryConstraints*) override final;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override final;
+ base::Status Init(int, const char* const*, SqliteTable::Schema*) final;
+ std::unique_ptr<SqliteTable::BaseCursor> CreateCursor() final;
+ base::Status ModifyConstraints(QueryConstraints*) final;
+ int BestIndex(const QueryConstraints&, BestIndexInfo*) final;
// These static functions are useful to allow other callers to make use
// of them.
diff --git a/src/trace_processor/sqlite/query_cache.h b/src/trace_processor/sqlite/query_cache.h
index f3b8223..1bb9d69 100644
--- a/src/trace_processor/sqlite/query_cache.h
+++ b/src/trace_processor/sqlite/query_cache.h
@@ -16,6 +16,7 @@
#ifndef SRC_TRACE_PROCESSOR_SQLITE_QUERY_CACHE_H_
#define SRC_TRACE_PROCESSOR_SQLITE_QUERY_CACHE_H_
+
#include <optional>
#include "src/trace_processor/db/table.h"
diff --git a/src/trace_processor/sqlite/sql_stats_table.cc b/src/trace_processor/sqlite/sql_stats_table.cc
index 73cac26..e6cdf87 100644
--- a/src/trace_processor/sqlite/sql_stats_table.cc
+++ b/src/trace_processor/sqlite/sql_stats_table.cc
@@ -22,6 +22,7 @@
#include <bitset>
#include <numeric>
+#include "perfetto/base/status.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/storage/trace_storage.h"
@@ -30,11 +31,7 @@
SqlStatsTable::SqlStatsTable(sqlite3*, const TraceStorage* storage)
: storage_(storage) {}
-
-void SqlStatsTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
- SqliteTable::Register<SqlStatsTable>(db, storage, "sqlstats",
- RegistrationFlags{});
-}
+SqlStatsTable::~SqlStatsTable() = default;
base::Status SqlStatsTable::Init(int, const char* const*, Schema* schema) {
*schema = Schema(
@@ -51,8 +48,8 @@
return util::OkStatus();
}
-std::unique_ptr<SqliteTable::Cursor> SqlStatsTable::CreateCursor() {
- return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
+std::unique_ptr<SqliteTable::BaseCursor> SqlStatsTable::CreateCursor() {
+ return std::unique_ptr<SqliteTable::BaseCursor>(new Cursor(this));
}
int SqlStatsTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
@@ -60,28 +57,29 @@
}
SqlStatsTable::Cursor::Cursor(SqlStatsTable* table)
- : SqliteTable::Cursor(table), storage_(table->storage_), table_(table) {}
-
+ : SqliteTable::BaseCursor(table),
+ storage_(table->storage_),
+ table_(table) {}
SqlStatsTable::Cursor::~Cursor() = default;
-int SqlStatsTable::Cursor::Filter(const QueryConstraints&,
- sqlite3_value**,
- FilterHistory) {
+base::Status SqlStatsTable::Cursor::Filter(const QueryConstraints&,
+ sqlite3_value**,
+ FilterHistory) {
*this = Cursor(table_);
num_rows_ = storage_->sql_stats().size();
- return SQLITE_OK;
+ return base::OkStatus();
}
-int SqlStatsTable::Cursor::Next() {
+base::Status SqlStatsTable::Cursor::Next() {
row_++;
- return SQLITE_OK;
+ return base::OkStatus();
}
-int SqlStatsTable::Cursor::Eof() {
+bool SqlStatsTable::Cursor::Eof() {
return row_ >= num_rows_;
}
-int SqlStatsTable::Cursor::Column(sqlite3_context* context, int col) {
+base::Status SqlStatsTable::Cursor::Column(sqlite3_context* context, int col) {
const TraceStorage::SqlStats& stats = storage_->sql_stats();
switch (col) {
case Column::kQuery:
@@ -98,7 +96,7 @@
sqlite3_result_int64(context, stats.times_ended()[row_]);
break;
}
- return SQLITE_OK;
+ return base::OkStatus();
}
} // namespace trace_processor
diff --git a/src/trace_processor/sqlite/sql_stats_table.h b/src/trace_processor/sqlite/sql_stats_table.h
index df8d9f5..d78224c 100644
--- a/src/trace_processor/sqlite/sql_stats_table.h
+++ b/src/trace_processor/sqlite/sql_stats_table.h
@@ -20,6 +20,7 @@
#include <limits>
#include <memory>
+#include "perfetto/base/status.h"
#include "src/trace_processor/sqlite/sqlite_table.h"
namespace perfetto {
@@ -30,7 +31,8 @@
// A virtual table that allows to introspect performances of the SQL engine
// for the kMaxLogEntries queries.
-class SqlStatsTable : public SqliteTable {
+class SqlStatsTable final
+ : public TypedSqliteTable<SqlStatsTable, const TraceStorage*> {
public:
enum Column {
kQuery = 0,
@@ -40,18 +42,18 @@
};
// Implementation of the SQLite cursor interface.
- class Cursor : public SqliteTable::Cursor {
+ class Cursor final : public SqliteTable::BaseCursor {
public:
- Cursor(SqlStatsTable* storage);
- ~Cursor() override;
+ explicit Cursor(SqlStatsTable* storage);
+ ~Cursor() final;
// Implementation of SqliteTable::Cursor.
- int Filter(const QueryConstraints&,
- sqlite3_value**,
- FilterHistory) override;
- int Next() override;
- int Eof() override;
- int Column(sqlite3_context*, int N) override;
+ base::Status Filter(const QueryConstraints&,
+ sqlite3_value**,
+ FilterHistory);
+ base::Status Next();
+ bool Eof();
+ base::Status Column(sqlite3_context*, int N);
private:
Cursor(Cursor&) = delete;
@@ -67,13 +69,12 @@
};
SqlStatsTable(sqlite3*, const TraceStorage* storage);
-
- static void RegisterTable(sqlite3* db, const TraceStorage* storage);
+ ~SqlStatsTable() final;
// Table implementation.
- base::Status Init(int, const char* const*, Schema*) override;
- std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+ base::Status Init(int, const char* const*, Schema*) final;
+ std::unique_ptr<SqliteTable::BaseCursor> CreateCursor() final;
+ int BestIndex(const QueryConstraints&, BestIndexInfo*) final;
private:
const TraceStorage* const storage_;
diff --git a/src/trace_processor/sqlite/sqlite_engine.cc b/src/trace_processor/sqlite/sqlite_engine.cc
index 429318a..7ffc3ed 100644
--- a/src/trace_processor/sqlite/sqlite_engine.cc
+++ b/src/trace_processor/sqlite/sqlite_engine.cc
@@ -15,8 +15,13 @@
*/
#include "src/trace_processor/sqlite/sqlite_engine.h"
+
+#include <utility>
+
+#include "perfetto/base/status.h"
#include "src/trace_processor/sqlite/db_sqlite_table.h"
#include "src/trace_processor/sqlite/query_cache.h"
+#include "src/trace_processor/sqlite/sqlite_table.h"
// In Android and Chromium tree builds, we don't have the percentile module.
// Just don't include it.
@@ -66,12 +71,83 @@
db_.reset(std::move(db));
}
-void SqliteEngine::RegisterTable(const Table& table, const std::string& name) {
- DbSqliteTable::RegisterTable(*db_, query_cache_.get(), &table, name);
+SqliteEngine::~SqliteEngine() {
+ // It is important to unregister any functions that have been registered with
+ // the database before destroying it. This is because functions can hold onto
+ // prepared statements, which must be finalized before database destruction.
+ for (auto it = fn_ctx_.GetIterator(); it; ++it) {
+ int ret = sqlite3_create_function_v2(db_.get(), it.key().first.c_str(),
+ it.key().second, SQLITE_UTF8, nullptr,
+ nullptr, nullptr, nullptr, nullptr);
+ PERFETTO_CHECK(ret == 0);
+ }
+ fn_ctx_.Clear();
+}
+
+void SqliteEngine::RegisterTable(const Table& table,
+ const std::string& table_name) {
+ DbSqliteTable::Context context{query_cache_.get(),
+ DbSqliteTable::TableComputation::kStatic,
+ &table, nullptr};
+ RegisterVirtualTableModule<DbSqliteTable>(table_name, std::move(context),
+ SqliteTable::kEponymousOnly, false);
+
+ // Register virtual tables into an internal 'perfetto_tables' table.
+ // This is used for iterating through all the tables during a database
+ // export.
+ char* insert_sql = sqlite3_mprintf(
+ "INSERT INTO perfetto_tables(name) VALUES('%q')", table_name.c_str());
+ char* error = nullptr;
+ sqlite3_exec(db_.get(), insert_sql, nullptr, nullptr, &error);
+ sqlite3_free(insert_sql);
+ if (error) {
+ PERFETTO_ELOG("Error adding table to perfetto_tables: %s", error);
+ sqlite3_free(error);
+ }
}
void SqliteEngine::RegisterTableFunction(std::unique_ptr<TableFunction> fn) {
- DbSqliteTable::RegisterTable(*db_, query_cache_.get(), std::move(fn));
+ std::string table_name = fn->TableName();
+ DbSqliteTable::Context context{query_cache_.get(),
+ DbSqliteTable::TableComputation::kDynamic,
+ nullptr, std::move(fn)};
+ RegisterVirtualTableModule<DbSqliteTable>(table_name, std::move(context),
+ SqliteTable::kEponymousOnly, false);
+}
+
+base::Status SqliteEngine::DeclareVirtualTable(const std::string& create_stmt) {
+ int res = sqlite3_declare_vtab(db_.get(), create_stmt.c_str());
+ if (res != SQLITE_OK) {
+ return base::ErrStatus("Declare vtab failed: %s",
+ sqlite3_errmsg(db_.get()));
+ }
+ return base::OkStatus();
+}
+
+base::Status SqliteEngine::SaveSqliteTable(const std::string& table_name,
+ std::unique_ptr<SqliteTable> table) {
+ auto res = saved_tables_.Insert(table_name, {});
+ if (!res.second) {
+ return base::ErrStatus("Table with name %s already is saved",
+ table_name.c_str());
+ }
+ *res.first = std::move(table);
+ return base::OkStatus();
+}
+
+base::StatusOr<std::unique_ptr<SqliteTable>> SqliteEngine::RestoreSqliteTable(
+ const std::string& table_name) {
+ auto* res = saved_tables_.Find(table_name);
+ if (!res) {
+ return base::ErrStatus("Table with name %s does not exist in saved state",
+ table_name.c_str());
+ }
+ return std::move(*res);
+}
+
+void* SqliteEngine::GetFunctionContext(const std::string& name, int argc) {
+ auto* res = fn_ctx_.Find(std::make_pair(name, argc));
+ return res ? *res : nullptr;
}
} // namespace trace_processor
diff --git a/src/trace_processor/sqlite/sqlite_engine.h b/src/trace_processor/sqlite/sqlite_engine.h
index f1ebdd3..2af8b81 100644
--- a/src/trace_processor/sqlite/sqlite_engine.h
+++ b/src/trace_processor/sqlite/sqlite_engine.h
@@ -18,11 +18,21 @@
#define SRC_TRACE_PROCESSOR_SQLITE_SQLITE_ENGINE_H_
#include <sqlite3.h>
+#include <stdint.h>
+#include <functional>
+#include <memory>
+#include <type_traits>
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/flat_hash_map.h"
+#include "perfetto/ext/base/hash.h"
#include "src/trace_processor/db/table.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
#include "src/trace_processor/prelude/table_functions/table_function.h"
#include "src/trace_processor/sqlite/query_cache.h"
#include "src/trace_processor/sqlite/scoped_db.h"
+#include "src/trace_processor/sqlite/sqlite_table.h"
+#include "src/trace_processor/sqlite/sqlite_utils.h"
namespace perfetto {
namespace trace_processor {
@@ -38,24 +48,216 @@
class SqliteEngine {
public:
SqliteEngine();
+ ~SqliteEngine();
// Registers a trace processor C++ table with SQLite with an SQL name of
// |name|.
void RegisterTable(const Table& table, const std::string& name);
- // Registers a trace processor C++ function with SQLite.
+ // Registers a trace processor C++ function to be runnable from SQL.
+ //
+ // The format of the function is given by the |SqlFunction|.
+ //
+ // |db|: sqlite3 database object
+ // |name|: name of the function in SQL
+ // |argc|: number of arguments for this function. This can be -1 if
+ // the number of arguments is variable.
+ // |ctx|: context object for the function (see SqlFunction::Run
+ // above);
+ // this object *must* outlive the function so should likely be
+ // either static or scoped to the lifetime of TraceProcessor.
+ // |determistic|: whether this function has deterministic output given the
+ // same set of arguments.
+ template <typename Function = SqlFunction>
+ base::Status RegisterSqlFunction(const char* name,
+ int argc,
+ typename Function::Context* ctx,
+ bool deterministic = true);
+
+ // Registers a trace processor C++ function to be runnable from SQL.
+ //
+ // This function is the same as the above except allows a unique_ptr to be
+ // passed for the context; this allows for SQLite to manage the lifetime of
+ // this pointer instead of the essentially static requirement of the context
+ // pointer above.
+ template <typename Function>
+ base::Status RegisterSqlFunction(
+ const char* name,
+ int argc,
+ std::unique_ptr<typename Function::Context> ctx,
+ bool deterministic = true);
+
+ // Registers a trace processor C++ table function with SQLite.
void RegisterTableFunction(std::unique_ptr<TableFunction> fn);
+ // Registers a SQLite virtual table module with the given name.
+ //
+ // This API only exists for internal/legacy use: most callers should use
+ // one of the RegisterTable* APIs above.
+ template <typename Vtab, typename Context>
+ void RegisterVirtualTableModule(const std::string& module_name,
+ Context ctx,
+ SqliteTable::TableType table_type,
+ bool updatable);
+
+ // Declares a virtual table with SQLite.
+ //
+ // This API only exists for internal use. Most callers should never call this
+ // directly: instead use one of the RegisterTable* APIs above.
+ base::Status DeclareVirtualTable(const std::string& create_stmt);
+
+ // Saves a SQLite table across a pair of xDisconnect/xConnect callbacks.
+ //
+ // This API only exists for internal use. Most callers should never call this
+ // directly.
+ base::Status SaveSqliteTable(const std::string& table_name,
+ std::unique_ptr<SqliteTable>);
+
+ // Restores a SQLite table across a pair of xDisconnect/xConnect callbacks.
+ //
+ // This API only exists for internal use. Most callers should never call this
+ // directly.
+ base::StatusOr<std::unique_ptr<SqliteTable>> RestoreSqliteTable(
+ const std::string& table_name);
+
+ // Gets the context for a registered SQL function.
+ //
+ // This API only exists for internal use. Most callers should never call this
+ // directly.
+ void* GetFunctionContext(const std::string& name, int argc);
+
sqlite3* db() const { return db_.get(); }
private:
- // Keep this first: we need this to be destroyed after we clean up
- // everything else.
- ScopedDb db_;
+ struct FnHasher {
+ size_t operator()(const std::pair<std::string, int>& x) const {
+ base::Hasher hasher;
+ hasher.Update(x.first);
+ hasher.Update(x.second);
+ return static_cast<size_t>(hasher.digest());
+ }
+ };
+
std::unique_ptr<QueryCache> query_cache_;
+ base::FlatHashMap<std::string, std::unique_ptr<SqliteTable>> saved_tables_;
+ base::FlatHashMap<std::pair<std::string, int>, void*, FnHasher> fn_ctx_;
+
+ ScopedDb db_;
};
} // namespace trace_processor
} // namespace perfetto
+// The rest of this file is just implementation details which we need
+// in the header file because it is templated code. We separate it out
+// like this to keep the API people actually care about easy to read.
+
+namespace perfetto {
+namespace trace_processor {
+namespace sqlite_internal {
+
+// RAII type to call Function::Cleanup when destroyed.
+template <typename Function>
+struct ScopedCleanup {
+ typename Function::Context* ctx;
+ ~ScopedCleanup() { Function::Cleanup(ctx); }
+};
+
+template <typename Function>
+void WrapSqlFunction(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
+ using Context = typename Function::Context;
+ Context* ud = static_cast<Context*>(sqlite3_user_data(ctx));
+
+ ScopedCleanup<Function> scoped_cleanup{ud};
+ SqlValue value{};
+ SqlFunction::Destructors destructors{};
+ base::Status status =
+ Function::Run(ud, static_cast<size_t>(argc), argv, value, destructors);
+ if (!status.ok()) {
+ sqlite3_result_error(ctx, status.c_message(), -1);
+ return;
+ }
+
+ if (Function::kVoidReturn) {
+ if (!value.is_null()) {
+ sqlite3_result_error(ctx, "void SQL function returned value", -1);
+ return;
+ }
+
+ // If the function doesn't want to return anything, set the "VOID"
+ // pointer type to a non-null value. Note that because of the weird
+ // way |sqlite3_value_pointer| works, we need to set some value even
+ // if we don't actually read it - just set it to a pointer to an empty
+ // string for this reason.
+ static char kVoidValue[] = "";
+ sqlite3_result_pointer(ctx, kVoidValue, "VOID", nullptr);
+ } else {
+ sqlite_utils::ReportSqlValue(ctx, value, destructors.string_destructor,
+ destructors.bytes_destructor);
+ }
+
+ status = Function::VerifyPostConditions(ud);
+ if (!status.ok()) {
+ sqlite3_result_error(ctx, status.c_message(), -1);
+ return;
+ }
+}
+
+} // namespace sqlite_internal
+
+template <typename Function>
+base::Status SqliteEngine::RegisterSqlFunction(const char* name,
+ int argc,
+ typename Function::Context* ctx,
+ bool deterministic) {
+ int flags = SQLITE_UTF8 | (deterministic ? SQLITE_DETERMINISTIC : 0);
+ int ret = sqlite3_create_function_v2(
+ db_.get(), name, static_cast<int>(argc), flags, ctx,
+ sqlite_internal::WrapSqlFunction<Function>, nullptr, nullptr, nullptr);
+ if (ret != SQLITE_OK) {
+ return base::ErrStatus("Unable to register function with name %s", name);
+ }
+ *fn_ctx_.Insert(std::make_pair(name, argc), ctx).first = ctx;
+ return base::OkStatus();
+}
+
+template <typename Function>
+base::Status SqliteEngine::RegisterSqlFunction(
+ const char* name,
+ int argc,
+ std::unique_ptr<typename Function::Context> user_data,
+ bool deterministic) {
+ int flags = SQLITE_UTF8 | (deterministic ? SQLITE_DETERMINISTIC : 0);
+ void* fn_ctx = user_data.get();
+ int ret = sqlite3_create_function_v2(
+ db_.get(), name, static_cast<int>(argc), flags, user_data.release(),
+ sqlite_internal::WrapSqlFunction<Function>, nullptr, nullptr,
+ [](void* ptr) { delete static_cast<typename Function::Context*>(ptr); });
+ if (ret != SQLITE_OK) {
+ return base::ErrStatus("Unable to register function with name %s", name);
+ }
+ *fn_ctx_.Insert(std::make_pair(name, argc), fn_ctx).first = fn_ctx;
+ return base::OkStatus();
+}
+
+template <typename Vtab, typename Context>
+void SqliteEngine::RegisterVirtualTableModule(const std::string& module_name,
+ Context ctx,
+ SqliteTable::TableType table_type,
+ bool updatable) {
+ static_assert(std::is_base_of_v<SqliteTable, Vtab>,
+ "Must subclass TypedSqliteTable");
+
+ auto module_arg =
+ Vtab::CreateModuleArg(this, std::move(ctx), table_type, updatable);
+ sqlite3_module* module = &module_arg->module;
+ int res = sqlite3_create_module_v2(
+ db_.get(), module_name.c_str(), module, module_arg.release(),
+ [](void* arg) { delete static_cast<typename Vtab::ModuleArg*>(arg); });
+ PERFETTO_CHECK(res == SQLITE_OK);
+}
+
+} // namespace trace_processor
+} // namespace perfetto
+
#endif // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_ENGINE_H_
diff --git a/src/trace_processor/sqlite/sqlite_table.cc b/src/trace_processor/sqlite/sqlite_table.cc
index a0c5ce9..2ad925c 100644
--- a/src/trace_processor/sqlite/sqlite_table.cc
+++ b/src/trace_processor/sqlite/sqlite_table.cc
@@ -20,9 +20,16 @@
#include <algorithm>
#include <cinttypes>
#include <map>
+#include <memory>
#include "perfetto/base/logging.h"
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/status_or.h"
+#include "perfetto/ext/base/string_view.h"
+#include "sqlite3.h"
+#include "src/trace_processor/sqlite/sqlite_engine.h"
#include "src/trace_processor/tp_metatrace.h"
+#include "src/trace_processor/util/status_macros.h"
namespace perfetto {
namespace trace_processor {
@@ -153,98 +160,16 @@
SqliteTable::SqliteTable() = default;
SqliteTable::~SqliteTable() = default;
-int SqliteTable::OpenInternal(sqlite3_vtab_cursor** ppCursor) {
- // Freed in xClose().
- *ppCursor = static_cast<sqlite3_vtab_cursor*>(CreateCursor().release());
- return SQLITE_OK;
-}
-
-int SqliteTable::BestIndexInternal(sqlite3_index_info* idx) {
- QueryConstraints qc(idx->colUsed);
-
- for (int i = 0; i < idx->nConstraint; i++) {
- const auto& cs = idx->aConstraint[i];
- if (!cs.usable)
- continue;
- qc.AddConstraint(cs.iColumn, cs.op, i);
- }
-
- for (int i = 0; i < idx->nOrderBy; i++) {
- int column = idx->aOrderBy[i].iColumn;
- bool desc = idx->aOrderBy[i].desc;
- qc.AddOrderBy(column, desc);
- }
-
- int ret = ModifyConstraints(&qc);
- if (ret != SQLITE_OK)
- return ret;
-
- BestIndexInfo info;
- info.estimated_cost = idx->estimatedCost;
- info.estimated_rows = idx->estimatedRows;
- info.sqlite_omit_constraint.resize(qc.constraints().size());
-
- ret = BestIndex(qc, &info);
-
- if (ret != SQLITE_OK)
- return ret;
-
- idx->orderByConsumed = qc.order_by().empty() || info.sqlite_omit_order_by;
- idx->estimatedCost = info.estimated_cost;
- idx->estimatedRows = info.estimated_rows;
-
- // First pass: mark all constraints as omitted to ensure that any pruned
- // constraints are not checked for by SQLite.
- for (int i = 0; i < idx->nConstraint; ++i) {
- auto& u = idx->aConstraintUsage[i];
- u.omit = true;
- }
-
- // Second pass: actually set the correct omit and index values for all
- // retained constraints.
- for (uint32_t i = 0; i < qc.constraints().size(); ++i) {
- auto& u = idx->aConstraintUsage[qc.constraints()[i].a_constraint_idx];
- u.omit = info.sqlite_omit_constraint[i];
- u.argvIndex = static_cast<int>(i) + 1;
- }
-
- PERFETTO_TP_TRACE(
- metatrace::Category::QUERY, "SQLITE_TABLE_BEST_INDEX",
- [&](metatrace::Record* r) {
- r->AddArg("name", name_);
- WriteQueryConstraintsToMetatrace(r, qc, schema());
- r->AddArg("order_by_consumed", std::to_string(idx->orderByConsumed));
- r->AddArg("estimated_cost", std::to_string(idx->estimatedCost));
- r->AddArg("estimated_rows",
- std::to_string(static_cast<int64_t>(idx->estimatedRows)));
- });
-
- auto out_qc_str = qc.ToNewSqlite3String();
- if (SqliteTable::debug) {
- PERFETTO_LOG(
- "[%s::BestIndex] constraints=%s orderByConsumed=%d estimatedCost=%f "
- "estimatedRows=%" PRId64,
- name_.c_str(), QcDebugStr(qc, schema()).c_str(), idx->orderByConsumed,
- idx->estimatedCost, static_cast<int64_t>(idx->estimatedRows));
- }
-
- idx->idxStr = out_qc_str.release();
- idx->needToFreeIdxStr = true;
- idx->idxNum = ++best_index_num_;
-
- return SQLITE_OK;
-}
-
-int SqliteTable::ModifyConstraints(QueryConstraints*) {
- return SQLITE_OK;
+base::Status SqliteTable::ModifyConstraints(QueryConstraints*) {
+ return base::OkStatus();
}
int SqliteTable::FindFunction(const char*, FindFunctionFn*, void**) {
return 0;
}
-int SqliteTable::Update(int, sqlite3_value**, sqlite3_int64*) {
- return SQLITE_READONLY;
+base::Status SqliteTable::Update(int, sqlite3_value**, sqlite3_int64*) {
+ return base::ErrStatus("Updating not supported");
}
bool SqliteTable::ReadConstraints(int idxNum, const char* idxStr, int argc) {
@@ -274,16 +199,20 @@
return cache_hit;
}
-SqliteTable::Cursor::Cursor(SqliteTable* table) : table_(table) {
+////////////////////////////////////////////////////////////////////////////////
+// SqliteTable::BaseCursor implementation
+////////////////////////////////////////////////////////////////////////////////
+
+SqliteTable::BaseCursor::BaseCursor(SqliteTable* table) : table_(table) {
// This is required to prevent us from leaving this field uninitialised if
// we ever move construct the Cursor.
pVtab = table;
}
-SqliteTable::Cursor::~Cursor() = default;
+SqliteTable::BaseCursor::~BaseCursor() = default;
-int SqliteTable::Cursor::RowId(sqlite3_int64*) {
- return SQLITE_ERROR;
-}
+////////////////////////////////////////////////////////////////////////////////
+// SqliteTable::Column implementation
+////////////////////////////////////////////////////////////////////////////////
SqliteTable::Column::Column(size_t index,
std::string name,
@@ -291,6 +220,12 @@
bool hidden)
: index_(index), name_(name), type_(type), hidden_(hidden) {}
+////////////////////////////////////////////////////////////////////////////////
+// SqliteTable::Schema implementation
+////////////////////////////////////////////////////////////////////////////////
+
+SqliteTable::Schema::Schema() = default;
+
SqliteTable::Schema::Schema(std::vector<Column> columns,
std::vector<size_t> primary_keys)
: columns_(std::move(columns)), primary_keys_(std::move(primary_keys)) {
@@ -302,7 +237,6 @@
}
}
-SqliteTable::Schema::Schema() = default;
SqliteTable::Schema::Schema(const Schema&) = default;
SqliteTable::Schema& SqliteTable::Schema::operator=(const Schema&) = default;
@@ -334,5 +268,170 @@
return stmt;
}
+////////////////////////////////////////////////////////////////////////////////
+// TypedSqliteTableBase implementation
+////////////////////////////////////////////////////////////////////////////////
+
+TypedSqliteTableBase::~TypedSqliteTableBase() = default;
+
+base::Status TypedSqliteTableBase::DeclareAndAssignVtab(
+ std::unique_ptr<SqliteTable> table,
+ sqlite3_vtab** tab) {
+ auto create_stmt = table->schema().ToCreateTableStmt();
+ PERFETTO_DLOG("Create table statement: %s", create_stmt.c_str());
+ RETURN_IF_ERROR(table->engine_->DeclareVirtualTable(create_stmt));
+ *tab = table.release();
+ return base::OkStatus();
+}
+
+int TypedSqliteTableBase::xDestroy(sqlite3_vtab* t) {
+ delete static_cast<SqliteTable*>(t);
+ return SQLITE_OK;
+}
+
+int TypedSqliteTableBase::xDestroyFatal(sqlite3_vtab*) {
+ PERFETTO_FATAL("xDestroy should not be called");
+}
+
+int TypedSqliteTableBase::xConnectRestoreTable(sqlite3*,
+ void* arg,
+ int,
+ const char* const* argv,
+ sqlite3_vtab** tab,
+ char** pzErr) {
+ auto* xArg = static_cast<BaseModuleArg*>(arg);
+
+ // SQLite guarantees that argv[2] contains the name of the table.
+ std::string table_name = argv[2];
+ base::StatusOr<std::unique_ptr<SqliteTable>> table =
+ xArg->engine->RestoreSqliteTable(table_name);
+ if (!table.status().ok()) {
+ *pzErr = sqlite3_mprintf("%s", table.status().c_message());
+ return SQLITE_ERROR;
+ }
+ base::Status status = DeclareAndAssignVtab(std::move(table.value()), tab);
+ if (!status.ok()) {
+ *pzErr = sqlite3_mprintf("%s", status.c_message());
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+}
+
+int TypedSqliteTableBase::xDisconnectSaveTable(sqlite3_vtab* t) {
+ auto* table = static_cast<TypedSqliteTableBase*>(t);
+ base::Status status = table->engine_->SaveSqliteTable(
+ table->name(), std::unique_ptr<SqliteTable>(table));
+ return table->SetStatusAndReturn(status);
+}
+
+base::Status TypedSqliteTableBase::InitInternal(SqliteEngine* engine,
+ int argc,
+ const char* const* argv) {
+ // Set the engine to allow saving into it later.
+ engine_ = engine;
+
+ // SQLite guarantees that argv[0] will be the "module" name: this is the
+ // same as |table_name| passed to the Register function.
+ module_name_ = argv[0];
+
+ // SQLite guarantees that argv[2] contains the name of the table: for
+ // non-arg taking tables, this will be the same as |table_name| but for
+ // arg-taking tables, this will be the table name as defined by the
+ // user in the CREATE VIRTUAL TABLE call.
+ name_ = argv[2];
+
+ Schema schema;
+ RETURN_IF_ERROR(Init(argc, argv, &schema));
+ schema_ = std::move(schema);
+ return base::OkStatus();
+}
+
+int TypedSqliteTableBase::xOpen(sqlite3_vtab* t,
+ sqlite3_vtab_cursor** ppCursor) {
+ auto* table = static_cast<TypedSqliteTableBase*>(t);
+ *ppCursor =
+ static_cast<sqlite3_vtab_cursor*>(table->CreateCursor().release());
+ return SQLITE_OK;
+}
+
+int TypedSqliteTableBase::xBestIndex(sqlite3_vtab* t, sqlite3_index_info* idx) {
+ auto* table = static_cast<TypedSqliteTableBase*>(t);
+
+ QueryConstraints qc(idx->colUsed);
+
+ for (int i = 0; i < idx->nConstraint; i++) {
+ const auto& cs = idx->aConstraint[i];
+ if (!cs.usable)
+ continue;
+ qc.AddConstraint(cs.iColumn, cs.op, i);
+ }
+
+ for (int i = 0; i < idx->nOrderBy; i++) {
+ int column = idx->aOrderBy[i].iColumn;
+ bool desc = idx->aOrderBy[i].desc;
+ qc.AddOrderBy(column, desc);
+ }
+
+ int ret = table->SetStatusAndReturn(table->ModifyConstraints(&qc));
+ if (ret != SQLITE_OK)
+ return ret;
+
+ BestIndexInfo info;
+ info.estimated_cost = idx->estimatedCost;
+ info.estimated_rows = idx->estimatedRows;
+ info.sqlite_omit_constraint.resize(qc.constraints().size());
+
+ ret = table->BestIndex(qc, &info);
+
+ if (ret != SQLITE_OK)
+ return ret;
+
+ idx->orderByConsumed = qc.order_by().empty() || info.sqlite_omit_order_by;
+ idx->estimatedCost = info.estimated_cost;
+ idx->estimatedRows = info.estimated_rows;
+
+ // First pass: mark all constraints as omitted to ensure that any pruned
+ // constraints are not checked for by SQLite.
+ for (int i = 0; i < idx->nConstraint; ++i) {
+ auto& u = idx->aConstraintUsage[i];
+ u.omit = true;
+ }
+
+ // Second pass: actually set the correct omit and index values for all
+ // retained constraints.
+ for (uint32_t i = 0; i < qc.constraints().size(); ++i) {
+ auto& u = idx->aConstraintUsage[qc.constraints()[i].a_constraint_idx];
+ u.omit = info.sqlite_omit_constraint[i];
+ u.argvIndex = static_cast<int>(i) + 1;
+ }
+
+ PERFETTO_TP_TRACE(
+ metatrace::Category::QUERY, "SQLITE_TABLE_BEST_INDEX",
+ [&](metatrace::Record* r) {
+ r->AddArg("name", table->name());
+ WriteQueryConstraintsToMetatrace(r, qc, table->schema());
+ r->AddArg("order_by_consumed", std::to_string(idx->orderByConsumed));
+ r->AddArg("estimated_cost", std::to_string(idx->estimatedCost));
+ r->AddArg("estimated_rows",
+ std::to_string(static_cast<int64_t>(idx->estimatedRows)));
+ });
+
+ auto out_qc_str = qc.ToNewSqlite3String();
+ if (SqliteTable::debug) {
+ PERFETTO_LOG(
+ "[%s::BestIndex] constraints=%s orderByConsumed=%d estimatedCost=%f "
+ "estimatedRows=%" PRId64,
+ table->name().c_str(), QcDebugStr(qc, table->schema()).c_str(),
+ idx->orderByConsumed, idx->estimatedCost,
+ static_cast<int64_t>(idx->estimatedRows));
+ }
+
+ idx->idxStr = out_qc_str.release();
+ idx->needToFreeIdxStr = true;
+ idx->idxNum = ++table->best_index_num_;
+
+ return SQLITE_OK;
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/sqlite/sqlite_table.h b/src/trace_processor/sqlite/sqlite_table.h
index 85ae8f4..2d0cabc 100644
--- a/src/trace_processor/sqlite/sqlite_table.h
+++ b/src/trace_processor/sqlite/sqlite_table.h
@@ -27,31 +27,30 @@
#include <vector>
#include "perfetto/base/status.h"
+#include "perfetto/ext/base/flat_hash_map.h"
+#include "perfetto/ext/base/status_or.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/db/table.h"
#include "src/trace_processor/sqlite/query_constraints.h"
namespace perfetto {
namespace trace_processor {
-class TraceStorage;
+class SqliteEngine;
+class TypedSqliteTableBase;
// Abstract base class representing a SQLite virtual table. Implements the
// common bookeeping required across all tables and allows subclasses to
// implement a friendlier API than that required by SQLite.
class SqliteTable : public sqlite3_vtab {
public:
- template <typename Context>
- using Factory =
- std::function<std::unique_ptr<SqliteTable>(sqlite3*, Context)>;
-
// Custom opcodes used by subclasses of SqliteTable.
// Stored here as we need a central repository of opcodes to prevent clashes
// between different sub-classes.
enum CustomFilterOpcode {
kSourceGeqOpCode = SQLITE_INDEX_CONSTRAINT_FUNCTION + 1,
};
-
// Describes a column of this table.
class Column {
public:
@@ -74,15 +73,9 @@
bool hidden_ = false;
};
- // When set it logs all BestIndex and Filter actions on the console.
- static bool debug;
-
- // Public for unique_ptr destructor calls.
- virtual ~SqliteTable();
-
// Abstract base class representing an SQLite Cursor. Presents a friendlier
// API for subclasses to implement.
- class Cursor : public sqlite3_vtab_cursor {
+ class BaseCursor : public sqlite3_vtab_cursor {
public:
// Enum for the history of calls to Filter.
enum class FilterHistory : uint32_t {
@@ -97,39 +90,39 @@
kSame = 1,
};
- explicit Cursor(SqliteTable* table);
- virtual ~Cursor();
+ explicit BaseCursor(SqliteTable* table);
+ virtual ~BaseCursor();
// Methods to be implemented by derived table classes.
+ // Note: these methods are intentionally not virtual for performance
+ // reasons. As these methods are not defined, there will be compile errors
+ // thrown if any of these methods are missing.
// Called to intialise the cursor with the constraints of the query.
- virtual int Filter(const QueryConstraints& qc,
- sqlite3_value**,
- FilterHistory) = 0;
+ base::Status Filter(const QueryConstraints& qc,
+ sqlite3_value**,
+ FilterHistory);
// Called to forward the cursor to the next row in the table.
- virtual int Next() = 0;
+ base::Status Next();
// Called to check if the cursor has reached eof. Column will be called iff
// this method returns true.
- virtual int Eof() = 0;
+ bool Eof();
// Used to extract the value from the column at index |N|.
- virtual int Column(sqlite3_context* context, int N) = 0;
+ base::Status Column(sqlite3_context* context, int N);
- // Optional methods to implement.
- virtual int RowId(sqlite3_int64*);
+ SqliteTable* table() const { return table_; }
protected:
- Cursor(Cursor&) = delete;
- Cursor& operator=(const Cursor&) = delete;
+ BaseCursor(BaseCursor&) = delete;
+ BaseCursor& operator=(const BaseCursor&) = delete;
- Cursor(Cursor&&) noexcept = default;
- Cursor& operator=(Cursor&&) = default;
+ BaseCursor(BaseCursor&&) noexcept = default;
+ BaseCursor& operator=(BaseCursor&&) = default;
private:
- friend class SqliteTable;
-
SqliteTable* table_ = nullptr;
};
@@ -159,6 +152,24 @@
std::vector<size_t> primary_keys_;
};
+ enum TableType {
+ // A table which automatically exists in the main schema and cannot be
+ // created with CREATE VIRTUAL TABLE.
+ // Note: the name value here matches the naming in the vtable docs of
+ // SQLite.
+ kEponymousOnly,
+
+ // A table which must be explicitly created using a CREATE VIRTUAL TABLE
+ // statement (i.e. does exist automatically).
+ kExplicitCreate,
+ };
+
+ // Public for unique_ptr destructor calls.
+ virtual ~SqliteTable();
+
+ // When set it logs all BestIndex and Filter actions on the console.
+ static bool debug;
+
protected:
// Populated by a BestIndex call to allow subclasses to tweak SQLite's
// handling of sets of constraints.
@@ -185,225 +196,39 @@
int64_t estimated_rows = 0;
};
- struct RegistrationFlags {
- // Specifies whether the table can also be written to.
- bool writable = false;
-
- enum TableType {
- // A table which automatically exists in the main schema and cannot be
- // created with CREATE VIRTUAL TABLE.
- // Note: the name value here matches the naming in the vtable docs of
- // SQLite.
- kEponymousOnly,
-
- // A table which automatically exists in the main schema and can also be
- // created with CREATE VIRTUAL TABLE.
- // Note: the name value here matches the naming in the vtable docs of
- // SQLite.
- kEponymous,
-
- // A table which must be explicitly created using a CREATE VIRTUAL TABLE
- // statement (i.e. does exist automatically) but does not have any
- // backing state beyond the arguments passed to it.
- kExplicitCreateStateless,
- };
- TableType type = TableType::kEponymousOnly;
-
- // Whether the table requires some number of hidden constraints to be passed
- // to be able to the queried (i.e. a SELECT * FROM table would not work).
- bool requires_hidden_constraints = false;
- };
-
SqliteTable();
- // Called by derived classes to register themselves with the SQLite db.
- // Note: this function is inlined here because we use the TTable template to
- // devirtualise the function calls.
- template <typename TTable, typename Context = const TraceStorage*>
- static void Register(sqlite3* db,
- Context ctx,
- const std::string& module_name,
- RegistrationFlags flags) {
- using TCursor = typename TTable::Cursor;
-
- struct TableDescriptor {
- SqliteTable::Factory<Context> factory;
- Context context;
- sqlite3_module module = {};
- };
-
- std::unique_ptr<TableDescriptor> desc(new TableDescriptor());
- desc->context = std::move(ctx);
- desc->factory = GetFactory<TTable, Context>();
- sqlite3_module* module = &desc->module;
- memset(module, 0, sizeof(*module));
-
- auto create_fn = [](sqlite3* xdb, void* arg, int argc,
- const char* const* argv, sqlite3_vtab** tab,
- char** pzErr) {
- auto* xdesc = static_cast<TableDescriptor*>(arg);
- auto table = xdesc->factory(xdb, std::move(xdesc->context));
-
- // SQLite guarantees that argv[0] will be the "module" name: this is the
- // same as |table_name| passed to the Register function.
- table->module_name_ = argv[0];
-
- // SQLite guarantees that argv[2] contains the name of the table: for
- // non-arg taking tables, this will be the same as |table_name| but for
- // arg-taking tables, this will be the table name as defined by the user
- // in the CREATE VIRTUAL TABLE call.
- table->name_ = argv[2];
-
- Schema schema;
- base::Status status = table->Init(argc, argv, &schema);
- if (!status.ok()) {
- *pzErr = sqlite3_mprintf("%s", status.c_message());
- return SQLITE_ERROR;
- }
-
- auto create_stmt = schema.ToCreateTableStmt();
- PERFETTO_DLOG("Create table statement: %s", create_stmt.c_str());
-
- int res = sqlite3_declare_vtab(xdb, create_stmt.c_str());
- if (res != SQLITE_OK)
- return res;
-
- // Freed in xDisconnect().
- table->schema_ = std::move(schema);
- *tab = table.release();
-
- return SQLITE_OK;
- };
- auto destroy_fn = [](sqlite3_vtab* t) {
- delete static_cast<TTable*>(t);
- return SQLITE_OK;
- };
-
- switch (flags.type) {
- case RegistrationFlags::kEponymousOnly:
- module->xCreate = nullptr;
- break;
- case RegistrationFlags::kEponymous:
- module->xCreate = create_fn;
- break;
- case RegistrationFlags::kExplicitCreateStateless:
- // TODO(lalitm): this is not accurate as we're basically creating an
- // eponymous table. Change this to be a different function once we can
- // do so easily.
- module->xCreate = create_fn;
- break;
- }
- module->xConnect = create_fn;
- module->xDisconnect = destroy_fn;
- module->xDestroy = destroy_fn;
- module->xOpen = [](sqlite3_vtab* t, sqlite3_vtab_cursor** c) {
- return static_cast<TTable*>(t)->OpenInternal(c);
- };
- module->xClose = [](sqlite3_vtab_cursor* c) {
- delete static_cast<TCursor*>(c);
- return SQLITE_OK;
- };
- module->xBestIndex = [](sqlite3_vtab* t, sqlite3_index_info* i) {
- return static_cast<TTable*>(t)->BestIndexInternal(i);
- };
- module->xFilter = [](sqlite3_vtab_cursor* vc, int i, const char* s, int a,
- sqlite3_value** v) {
- auto* c = static_cast<Cursor*>(vc);
- bool is_cached = c->table_->ReadConstraints(i, s, a);
-
- auto history = is_cached ? Cursor::FilterHistory::kSame
- : Cursor::FilterHistory::kDifferent;
- return static_cast<TCursor*>(c)->Filter(c->table_->qc_cache_, v, history);
- };
- module->xNext = [](sqlite3_vtab_cursor* c) {
- return static_cast<TCursor*>(c)->Next();
- };
- module->xEof = [](sqlite3_vtab_cursor* c) {
- return static_cast<TCursor*>(c)->Eof();
- };
- module->xColumn = [](sqlite3_vtab_cursor* c, sqlite3_context* a, int b) {
- return static_cast<TCursor*>(c)->Column(a, b);
- };
- module->xRowid = [](sqlite3_vtab_cursor* c, sqlite3_int64* r) {
- return static_cast<TCursor*>(c)->RowId(r);
- };
- module->xFindFunction =
- [](sqlite3_vtab* t, int, const char* name,
- void (**fn)(sqlite3_context*, int, sqlite3_value**), void** args) {
- return static_cast<TTable*>(t)->FindFunction(name, fn, args);
- };
-
- if (flags.writable) {
- module->xUpdate = [](sqlite3_vtab* t, int a, sqlite3_value** v,
- sqlite3_int64* r) {
- return static_cast<TTable*>(t)->Update(a, v, r);
- };
- }
-
- int res = sqlite3_create_module_v2(
- db, module_name.c_str(), module, desc.release(),
- [](void* arg) { delete static_cast<TableDescriptor*>(arg); });
- PERFETTO_CHECK(res == SQLITE_OK);
-
- // Register virtual tables into an internal 'perfetto_tables' table. This is
- // used for iterating through all the tables during a database export. Note
- // that virtual tables which requires explicit CREATE statements or require
- // hidden constraints cannot be inserted.
- bool explicit_create =
- flags.type == RegistrationFlags::kExplicitCreateStateless;
- if (!explicit_create && !flags.requires_hidden_constraints) {
- char* insert_sql =
- sqlite3_mprintf("INSERT INTO perfetto_tables(name) VALUES('%q')",
- module_name.c_str());
- char* error = nullptr;
- sqlite3_exec(db, insert_sql, nullptr, nullptr, &error);
- sqlite3_free(insert_sql);
- if (error) {
- PERFETTO_ELOG("Error registering table: %s", error);
- sqlite3_free(error);
- }
- }
- }
-
// Methods to be implemented by derived table classes.
virtual base::Status Init(int argc, const char* const* argv, Schema*) = 0;
- virtual std::unique_ptr<Cursor> CreateCursor() = 0;
+ virtual std::unique_ptr<BaseCursor> CreateCursor() = 0;
virtual int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) = 0;
// Optional metods to implement.
using FindFunctionFn = void (*)(sqlite3_context*, int, sqlite3_value**);
- virtual int ModifyConstraints(QueryConstraints* qc);
+ virtual base::Status ModifyConstraints(QueryConstraints* qc);
virtual int FindFunction(const char* name, FindFunctionFn* fn, void** args);
// At registration time, the function should also pass true for |read_write|.
- virtual int Update(int, sqlite3_value**, sqlite3_int64*);
+ virtual base::Status Update(int, sqlite3_value**, sqlite3_int64*);
- void SetErrorMessage(char* error) {
- sqlite3_free(zErrMsg);
- zErrMsg = error;
- }
+ bool ReadConstraints(int idxNum, const char* idxStr, int argc);
const Schema& schema() const { return schema_; }
const std::string& module_name() const { return module_name_; }
const std::string& name() const { return name_; }
private:
- template <typename TableType, typename Context>
- static Factory<Context> GetFactory() {
- return [](sqlite3* db, Context ctx) {
- return std::unique_ptr<SqliteTable>(new TableType(db, std::move(ctx)));
- };
- }
-
- bool ReadConstraints(int idxNum, const char* idxStr, int argc);
-
- // Overriden functions from sqlite3_vtab.
- int OpenInternal(sqlite3_vtab_cursor**);
- int BestIndexInternal(sqlite3_index_info*);
+ template <typename, typename>
+ friend class TypedSqliteTable;
+ friend class TypedSqliteTableBase;
SqliteTable(const SqliteTable&) = delete;
SqliteTable& operator=(const SqliteTable&) = delete;
+ // The engine class this table is registered with. Used for restoring/saving
+ // the table.
+ SqliteEngine* engine_ = nullptr;
+
// This name of the table. For tables created using CREATE VIRTUAL TABLE, this
// will be the name of the table specified by the query. For automatically
// created tables, this will be the same as the module name passed to
@@ -422,6 +247,177 @@
int best_index_num_ = 0;
};
+class TypedSqliteTableBase : public SqliteTable {
+ protected:
+ struct BaseModuleArg {
+ sqlite3_module module;
+ SqliteEngine* engine;
+ };
+
+ ~TypedSqliteTableBase() override;
+
+ static int xDestroy(sqlite3_vtab*);
+ static int xDestroyFatal(sqlite3_vtab*);
+
+ static int xConnectRestoreTable(sqlite3* xdb,
+ void* arg,
+ int argc,
+ const char* const* argv,
+ sqlite3_vtab** tab,
+ char** pzErr);
+ static int xDisconnectSaveTable(sqlite3_vtab*);
+
+ static int xOpen(sqlite3_vtab*, sqlite3_vtab_cursor**);
+ static int xBestIndex(sqlite3_vtab*, sqlite3_index_info*);
+
+ static base::Status DeclareAndAssignVtab(std::unique_ptr<SqliteTable> table,
+ sqlite3_vtab** tab);
+
+ base::Status InitInternal(SqliteEngine* engine,
+ int argc,
+ const char* const* argv);
+
+ int SetStatusAndReturn(base::Status status) {
+ if (!status.ok()) {
+ sqlite3_free(zErrMsg);
+ zErrMsg = sqlite3_mprintf("%s", status.c_message());
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+ }
+};
+
+template <typename SubTable, typename Context>
+class TypedSqliteTable : public TypedSqliteTableBase {
+ public:
+ struct ModuleArg : BaseModuleArg {
+ Context context;
+ };
+
+ static std::unique_ptr<ModuleArg> CreateModuleArg(SqliteEngine* engine,
+ Context ctx,
+ TableType table_type,
+ bool updatable) {
+ auto arg = std::make_unique<ModuleArg>();
+ arg->module = CreateModule(table_type, updatable);
+ arg->engine = engine;
+ arg->context = std::move(ctx);
+ return arg;
+ }
+
+ private:
+ static constexpr sqlite3_module CreateModule(TableType table_type,
+ bool updatable) {
+ sqlite3_module module;
+ memset(&module, 0, sizeof(sqlite3_module));
+ switch (table_type) {
+ case TableType::kEponymousOnly:
+ // Neither xCreate nor xDestroy should ever be called for
+ // eponymous-only tables.
+ module.xCreate = nullptr;
+ module.xDestroy = &xDestroyFatal;
+
+ // xConnect and xDisconnect will automatically be called with
+ // |module_name| == |name|.
+ module.xConnect = &xCreate;
+ module.xDisconnect = &xDestroy;
+ break;
+ case TableType::kExplicitCreate:
+ // xConnect and xDestroy will be called when the table is CREATE-ed and
+ // DROP-ed respectively.
+ module.xCreate = &xCreate;
+ module.xDestroy = &xDestroy;
+
+ // xConnect and xDisconnect can be called at any time.
+ module.xConnect = &xConnectRestoreTable;
+ module.xDisconnect = &xDisconnectSaveTable;
+ break;
+ }
+ module.xOpen = &xOpen;
+ module.xClose = &xClose;
+ module.xBestIndex = &xBestIndex;
+ module.xFindFunction = &xFindFunction;
+ module.xFilter = &xFilter;
+ module.xNext = &xNext;
+ module.xEof = &xEof;
+ module.xColumn = &xColumn;
+ module.xRowid = &xRowid;
+ if (updatable) {
+ module.xUpdate = &xUpdate;
+ }
+ return module;
+ }
+
+ static int xCreate(sqlite3* xdb,
+ void* arg,
+ int argc,
+ const char* const* argv,
+ sqlite3_vtab** tab,
+ char** pzErr) {
+ auto* xdesc = static_cast<ModuleArg*>(arg);
+ std::unique_ptr<SubTable> table(
+ new SubTable(xdb, std::move(xdesc->context)));
+ base::Status status = table->InitInternal(xdesc->engine, argc, argv);
+ if (!status.ok()) {
+ *pzErr = sqlite3_mprintf("%s", status.c_message());
+ return SQLITE_ERROR;
+ }
+ status = DeclareAndAssignVtab(std::move(table), tab);
+ if (!status.ok()) {
+ *pzErr = sqlite3_mprintf("%s", status.c_message());
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+ }
+ static int xClose(sqlite3_vtab_cursor* c) {
+ delete static_cast<typename SubTable::Cursor*>(c);
+ return SQLITE_OK;
+ }
+ static int xFindFunction(sqlite3_vtab* t,
+ int,
+ const char* name,
+ void (**fn)(sqlite3_context*, int, sqlite3_value**),
+ void** args) {
+ return static_cast<SubTable*>(t)->FindFunction(name, fn, args);
+ }
+ static int xFilter(sqlite3_vtab_cursor* vc,
+ int i,
+ const char* s,
+ int a,
+ sqlite3_value** v) {
+ auto* cursor = static_cast<typename SubTable::Cursor*>(vc);
+ bool is_cached = cursor->table()->ReadConstraints(i, s, a);
+ auto history = is_cached ? BaseCursor::FilterHistory::kSame
+ : BaseCursor::FilterHistory::kDifferent;
+ auto* table = static_cast<SubTable*>(cursor->table());
+ return table->SetStatusAndReturn(
+ cursor->Filter(cursor->table()->qc_cache_, v, history));
+ }
+ static int xNext(sqlite3_vtab_cursor* c) {
+ auto* cursor = static_cast<typename SubTable::Cursor*>(c);
+ auto* table = static_cast<SubTable*>(cursor->table());
+ return table->SetStatusAndReturn(cursor->Next());
+ }
+ static int xEof(sqlite3_vtab_cursor* c) {
+ return static_cast<int>(static_cast<typename SubTable::Cursor*>(c)->Eof());
+ }
+ static int xColumn(sqlite3_vtab_cursor* c, sqlite3_context* a, int b) {
+ auto* cursor = static_cast<typename SubTable::Cursor*>(c);
+ auto* table = static_cast<SubTable*>(cursor->table());
+ return table->SetStatusAndReturn(cursor->Column(a, b));
+ }
+ static int xRowid(sqlite3_vtab_cursor*, sqlite3_int64*) {
+ return SQLITE_ERROR;
+ }
+ static int xUpdate(sqlite3_vtab* t,
+ int a,
+ sqlite3_value** v,
+ sqlite3_int64* r) {
+ auto* table = static_cast<SubTable*>(t);
+ return table->SetStatusAndReturn(table->Update(a, v, r));
+ }
+};
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/sqlite/stats_table.cc b/src/trace_processor/sqlite/stats_table.cc
index 117e27d..296a2f5 100644
--- a/src/trace_processor/sqlite/stats_table.cc
+++ b/src/trace_processor/sqlite/stats_table.cc
@@ -16,6 +16,7 @@
#include "src/trace_processor/sqlite/stats_table.h"
+#include "perfetto/base/status.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
namespace perfetto {
@@ -24,9 +25,7 @@
StatsTable::StatsTable(sqlite3*, const TraceStorage* storage)
: storage_(storage) {}
-void StatsTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
- SqliteTable::Register<StatsTable>(db, storage, "stats", RegistrationFlags{});
-}
+StatsTable::~StatsTable() = default;
util::Status StatsTable::Init(int, const char* const*, Schema* schema) {
*schema = Schema(
@@ -46,8 +45,8 @@
return util::OkStatus();
}
-std::unique_ptr<SqliteTable::Cursor> StatsTable::CreateCursor() {
- return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
+std::unique_ptr<SqliteTable::BaseCursor> StatsTable::CreateCursor() {
+ return std::unique_ptr<SqliteTable::BaseCursor>(new Cursor(this));
}
int StatsTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
@@ -55,16 +54,20 @@
}
StatsTable::Cursor::Cursor(StatsTable* table)
- : SqliteTable::Cursor(table), table_(table), storage_(table->storage_) {}
+ : SqliteTable::BaseCursor(table),
+ table_(table),
+ storage_(table->storage_) {}
-int StatsTable::Cursor::Filter(const QueryConstraints&,
- sqlite3_value**,
- FilterHistory) {
+StatsTable::Cursor::~Cursor() = default;
+
+base::Status StatsTable::Cursor::Filter(const QueryConstraints&,
+ sqlite3_value**,
+ FilterHistory) {
*this = Cursor(table_);
- return SQLITE_OK;
+ return base::OkStatus();
}
-int StatsTable::Cursor::Column(sqlite3_context* ctx, int N) {
+base::Status StatsTable::Cursor::Column(sqlite3_context* ctx, int N) {
const auto kSqliteStatic = sqlite_utils::kSqliteStatic;
switch (N) {
case Column::kName:
@@ -114,16 +117,16 @@
PERFETTO_FATAL("Unknown column %d", N);
break;
}
- return SQLITE_OK;
+ return base::OkStatus();
}
-int StatsTable::Cursor::Next() {
+base::Status StatsTable::Cursor::Next() {
static_assert(stats::kTypes[0] == stats::kSingle,
"the first stats entry cannot be indexed");
const auto* cur_entry = &storage_->stats()[key_];
if (stats::kTypes[key_] == stats::kIndexed) {
if (++index_ != cur_entry->indexed_values.end()) {
- return SQLITE_OK;
+ return base::OkStatus();
}
}
while (++key_ < stats::kNumKeys) {
@@ -134,10 +137,10 @@
break;
}
}
- return SQLITE_OK;
+ return base::OkStatus();
}
-int StatsTable::Cursor::Eof() {
+bool StatsTable::Cursor::Eof() {
return key_ >= stats::kNumKeys;
}
diff --git a/src/trace_processor/sqlite/stats_table.h b/src/trace_processor/sqlite/stats_table.h
index 3213a2a..2824cb6 100644
--- a/src/trace_processor/sqlite/stats_table.h
+++ b/src/trace_processor/sqlite/stats_table.h
@@ -30,20 +30,22 @@
// The stats table contains diagnostic info and errors that are either:
// - Collected at trace time (e.g., ftrace buffer overruns).
// - Generated at parsing time (e.g., clock events out-of-order).
-class StatsTable : public SqliteTable {
+class StatsTable final
+ : public TypedSqliteTable<StatsTable, const TraceStorage*> {
public:
enum Column { kName = 0, kIndex, kSeverity, kSource, kValue, kDescription };
- class Cursor : public SqliteTable::Cursor {
+ class Cursor final : public SqliteTable::BaseCursor {
public:
- Cursor(StatsTable*);
+ explicit Cursor(StatsTable*);
+ ~Cursor() final;
// Implementation of SqliteTable::Cursor.
- int Filter(const QueryConstraints&,
- sqlite3_value**,
- FilterHistory) override;
- int Next() override;
- int Eof() override;
- int Column(sqlite3_context*, int N) override;
+ base::Status Filter(const QueryConstraints&,
+ sqlite3_value**,
+ FilterHistory);
+ base::Status Next();
+ bool Eof();
+ base::Status Column(sqlite3_context*, int N);
private:
Cursor(Cursor&) = delete;
@@ -58,14 +60,13 @@
TraceStorage::Stats::IndexMap::const_iterator index_{};
};
- static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
StatsTable(sqlite3*, const TraceStorage*);
+ ~StatsTable() final;
// Table implementation.
- util::Status Init(int, const char* const*, SqliteTable::Schema*) override;
- std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+ util::Status Init(int, const char* const*, SqliteTable::Schema*) final;
+ std::unique_ptr<SqliteTable::BaseCursor> CreateCursor() final;
+ int BestIndex(const QueryConstraints&, BestIndexInfo*) final;
private:
const TraceStorage* const storage_;
diff --git a/src/trace_processor/stdlib/android/BUILD.gn b/src/trace_processor/stdlib/android/BUILD.gn
index 86bdf6d..9596be8 100644
--- a/src/trace_processor/stdlib/android/BUILD.gn
+++ b/src/trace_processor/stdlib/android/BUILD.gn
@@ -18,9 +18,12 @@
deps = [ "startup" ]
sources = [
"battery.sql",
+ "battery_stats.sql",
"binder.sql",
"monitor_contention.sql",
+ "network_packets.sql",
"process_metadata.sql",
"slices.sql",
+ "statsd.sql",
]
}
diff --git a/src/trace_processor/stdlib/android/battery_stats.sql b/src/trace_processor/stdlib/android/battery_stats.sql
new file mode 100644
index 0000000..2507cb1
--- /dev/null
+++ b/src/trace_processor/stdlib/android/battery_stats.sql
@@ -0,0 +1,210 @@
+--
+-- Copyright 2023 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.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 IMPORT('common.timestamps');
+
+-- Converts a battery_stats counter value to human readable string.
+--
+-- @arg track STRING The counter track name (e.g. 'battery_stats.audio').
+-- @arg value LONG The counter value.
+-- @ret STRING The human-readable name for the counter value.
+SELECT CREATE_FUNCTION(
+ 'BATTERY_STATS_COUNTER_TO_STRING(track STRING, value FLOAT)',
+ 'STRING',
+ '
+ SELECT
+ CASE
+ WHEN ($track = "battery_stats.wifi_scan" OR
+ $track = "battery_stats.wifi_radio" OR
+ $track = "battery_stats.mobile_radio" OR
+ $track = "battery_stats.audio" OR
+ $track = "battery_stats.video" OR
+ $track = "battery_stats.camera" OR
+ $track = "battery_stats.power_save" OR
+ $track = "battery_stats.phone_in_call")
+ THEN
+ CASE $value
+ WHEN 0 THEN "inactive"
+ WHEN 1 THEN "active"
+ ELSE "unknown"
+ END
+ WHEN $track = "battery_stats.wifi"
+ THEN
+ CASE $value
+ WHEN 0 THEN "off"
+ WHEN 1 THEN "on"
+ ELSE "unknown"
+ END
+ WHEN $track = "battery_stats.phone_state"
+ THEN
+ CASE $value
+ WHEN 0 THEN "in"
+ WHEN 1 THEN "out"
+ WHEN 2 THEN "emergency"
+ WHEN 3 THEN "off"
+ ELSE "unknown"
+ END
+ WHEN ($track = "battery_stats.phone_signal_strength" OR
+ $track = "battery_stats.wifi_signal_strength")
+ THEN
+ CASE $value
+ WHEN 0 THEN "none"
+ WHEN 1 THEN "poor"
+ WHEN 2 THEN "moderate"
+ WHEN 3 THEN "good"
+ WHEN 4 THEN "great"
+ ELSE "unknown"
+ END
+ WHEN $track = "battery_stats.wifi_suppl"
+ THEN
+ CASE $value
+ WHEN 0 THEN "invalid"
+ WHEN 1 THEN "disconn"
+ WHEN 2 THEN "disabled"
+ WHEN 3 THEN "inactive"
+ WHEN 4 THEN "scanning"
+ WHEN 5 THEN "authenticating"
+ WHEN 6 THEN "associating"
+ WHEN 7 THEN "associated"
+ WHEN 8 THEN "4-way-handshake"
+ WHEN 9 THEN "group-handshake"
+ WHEN 10 THEN "completed"
+ WHEN 11 THEN "dormant"
+ WHEN 12 THEN "uninit"
+ ELSE "unknown"
+ END
+ WHEN $track = "battery_stats.data_conn"
+ THEN
+ CASE $value
+ WHEN 0 THEN "oos"
+ WHEN 1 THEN "gprs"
+ WHEN 2 THEN "edge"
+ WHEN 3 THEN "umts"
+ WHEN 4 THEN "cdma"
+ WHEN 5 THEN "evdo_0"
+ WHEN 6 THEN "evdo_A"
+ WHEN 7 THEN "1xrtt"
+ WHEN 8 THEN "hsdpa"
+ WHEN 9 THEN "hsupa"
+ WHEN 10 THEN "hspa"
+ WHEN 11 THEN "iden"
+ WHEN 12 THEN "evdo_b"
+ WHEN 13 THEN "lte"
+ WHEN 14 THEN "ehrpd"
+ WHEN 15 THEN "hspap"
+ WHEN 16 THEN "gsm"
+ WHEN 17 THEN "td_scdma"
+ WHEN 18 THEN "iwlan"
+ WHEN 19 THEN "lte_ca"
+ WHEN 20 THEN "nr"
+ WHEN 21 THEN "emngcy"
+ WHEN 22 THEN "other"
+ ELSE "unknown"
+ END
+ ELSE CAST($value AS text)
+ END
+ '
+);
+
+
+-- View of human readable battery stats counter-based states. These are recorded
+-- by BatteryStats as a bitmap where each 'category' has a unique value at any
+-- given time.
+--
+-- @column ts Timestamp in nanoseconds.
+-- @column dur The duration the state was active.
+-- @column track_name The name of the counter track.
+-- @column value The counter value as a number.
+-- @column value_name The counter value as a human-readable string.
+CREATE VIEW android_battery_stats_state AS
+SELECT
+ ts,
+ name AS track_name,
+ CAST(value AS INT64) AS value,
+ BATTERY_STATS_COUNTER_TO_STRING(name, value) AS value_name,
+ IFNULL(LEAD(ts) OVER (PARTITION BY track_id ORDER BY ts) - ts, -1) AS dur
+FROM counter
+JOIN counter_track
+ ON counter.track_id = counter_track.id
+WHERE counter_track.name GLOB 'battery_stats.*';
+
+
+-- View of slices derived from battery_stats events. Battery stats records all
+-- events as instants, however some may indicate whether something started or
+-- stopped with a '+' or '-' prefix. Events such as jobs, top apps, foreground
+-- apps or long wakes include these details and allow drawing slices between
+-- instant events found in a trace.
+--
+-- For example, we may see an event like the following on 'battery_stats.top':
+--
+-- -top=10215:"com.google.android.apps.nexuslauncher"
+--
+-- This view will find the associated start ('+top') with the matching suffix
+-- (everything after the '=') to construct a slice. It computes the timestamp
+-- and duration from the events and extract the details as follows:
+--
+-- track_name='battery_stats.top'
+-- str_value='com.google.android.apps.nexuslauncher'
+-- int_value=10215
+--
+-- @column track_name The battery stats track name.
+-- @column ts Timestamp in nanoseconds.
+-- @column dur The duration of the event.
+-- @column str_value The string part of the event identifier.
+-- @column int_value The integer part of the event identifier.
+CREATE VIEW android_battery_stats_event_slices AS
+WITH
+ event_markers AS (
+ SELECT
+ ts,
+ track.name AS track_name,
+ str_split(slice.name, '=', 1) AS key,
+ substr(slice.name, 1, 1) = '+' AS start
+ FROM slice
+ JOIN track
+ ON slice.track_id = track.id
+ WHERE
+ track_name GLOB 'battery_stats.*'
+ AND substr(slice.name, 1, 1) IN ('+', '-')
+ ),
+ with_neighbors AS (
+ SELECT
+ *,
+ LAG(ts) OVER (PARTITION BY track_name, key ORDER BY ts) AS last_ts,
+ LEAD(ts) OVER (PARTITION BY track_name, key ORDER BY ts) AS next_ts
+ FROM event_markers
+ ),
+ -- Note: query performance depends on the ability to push down filters on
+ -- the track_name. It would be more clear below to have two queries and union
+ -- them, but doing so prevents push down through the above window functions.
+ event_spans AS (
+ SELECT
+ track_name, key,
+ IIF(start, ts, TRACE_START()) AS ts,
+ IIF(start, next_ts, ts) AS end_ts
+ FROM with_neighbors
+ -- For the majority of events, we take the `start` event and compute the dur
+ -- based on next_ts. In the off chance we get an end event with no prior
+ -- start (matched by the second half of this where), we can create an event
+ -- starting from the beginning of the trace ending at the current event.
+ WHERE (start OR last_ts IS NULL)
+ )
+SELECT
+ ts,
+ IFNULL(end_ts-ts, -1) AS dur,
+ track_name,
+ str_split(key, '"', 1) AS str_value,
+ CAST(str_split(key, ':', 0) AS INT64) AS int_value
+FROM event_spans;
diff --git a/src/trace_processor/stdlib/android/binder.sql b/src/trace_processor/stdlib/android/binder.sql
index 51a9d75..a31fff0 100644
--- a/src/trace_processor/stdlib/android/binder.sql
+++ b/src/trace_processor/stdlib/android/binder.sql
@@ -90,6 +90,7 @@
thread.name AS thread_name,
thread.utid AS utid,
thread.tid AS tid,
+ process.pid AS pid,
process.upid AS upid,
slice.ts,
slice.dur,
@@ -112,6 +113,7 @@
reply_process.name AS server_process,
reply_thread.utid AS server_utid,
reply_thread.tid AS server_tid,
+ reply_process.pid AS server_pid,
reply_process.upid AS server_upid,
aidl.name AS aidl_name
FROM binder_txn
@@ -132,6 +134,7 @@
upid AS client_upid,
utid AS client_utid,
tid AS client_tid,
+ pid AS client_pid,
is_main_thread,
ts AS client_ts,
dur AS client_dur,
@@ -141,6 +144,7 @@
server_upid,
server_utid,
server_tid,
+ server_pid,
server_ts,
server_dur
FROM binder_reply
diff --git a/src/trace_processor/stdlib/android/monitor_contention.sql b/src/trace_processor/stdlib/android/monitor_contention.sql
index c1de58f..595c1fe 100644
--- a/src/trace_processor/stdlib/android/monitor_contention.sql
+++ b/src/trace_processor/stdlib/android/monitor_contention.sql
@@ -192,10 +192,13 @@
slice.dur,
slice.track_id,
thread.is_main_thread AS is_blocked_thread_main,
+ thread.tid AS blocked_thread_tid,
blocking_thread.is_main_thread AS is_blocking_thread_main,
+ blocking_thread.tid AS blocking_thread_tid,
binder_reply.id AS binder_reply_id,
binder_reply.ts AS binder_reply_ts,
- binder_reply_thread.tid AS binder_reply_tid
+ binder_reply_thread.tid AS binder_reply_tid,
+ process.pid
FROM slice
JOIN thread_track
ON thread_track.id = slice.track_id
diff --git a/src/trace_processor/stdlib/android/network_packets.sql b/src/trace_processor/stdlib/android/network_packets.sql
new file mode 100644
index 0000000..a88615a
--- /dev/null
+++ b/src/trace_processor/stdlib/android/network_packets.sql
@@ -0,0 +1,52 @@
+--
+-- Copyright 2023 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.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.
+
+-- Android network packet events (from android.network_packets data source).
+--
+-- @column ts Timestamp in nanoseconds.
+-- @column dur Duration (non-zero only in aggregate events)
+-- @column track_name The track name (interface and direction)
+-- @column package_name Traffic package source (or uid=$X if not found)
+-- @column iface Traffic interface name (linux interface name)
+-- @column direction Traffic direction ('Transmitted' or 'Received')
+-- @column packet_count Number of packets in this event
+-- @column packet_length Number of bytes in this event (wire size)
+-- @column packet_transport Transport used for traffic in this event
+-- @column packet_tcp_flags TCP flags used by tcp frames in this event
+-- @column socket_tag The Android traffic tag of the network socket
+-- @column socket_uid The Linux user id of the network socket
+-- @column local_port The local port number (for udp or tcp only)
+-- @column remote_port The remote port number (for udp or tcp only)
+CREATE VIEW android_network_packets AS
+SELECT
+ ts,
+ dur,
+ track.name AS track_name,
+ slice.name AS package_name,
+ str_split(track.name, ' ', 0) AS iface,
+ str_split(track.name, ' ', 1) AS direction,
+ ifnull(extract_arg(arg_set_id, 'packet_count'), 1) AS packet_count,
+ extract_arg(arg_set_id, 'packet_length') AS packet_length,
+ extract_arg(arg_set_id, 'packet_transport') AS packet_transport,
+ extract_arg(arg_set_id, 'packet_tcp_flags') AS packet_tcp_flags,
+ extract_arg(arg_set_id, 'socket_tag') AS socket_tag,
+ extract_arg(arg_set_id, 'socket_uid') AS socket_uid,
+ extract_arg(arg_set_id, 'local_port') AS local_port,
+ extract_arg(arg_set_id, 'remote_port') AS remote_port
+FROM slice
+JOIN track
+ ON slice.track_id = track.id
+WHERE (track.name GLOB '* Transmitted' OR
+ track.name GLOB '* Received');
diff --git a/src/trace_processor/stdlib/android/process_metadata.sql b/src/trace_processor/stdlib/android/process_metadata.sql
index 20fb82e..6154f00 100644
--- a/src/trace_processor/stdlib/android/process_metadata.sql
+++ b/src/trace_processor/stdlib/android/process_metadata.sql
@@ -50,11 +50,19 @@
LEFT JOIN internal_uid_package_count ON process.android_appid = internal_uid_package_count.uid
LEFT JOIN package_list plist
ON (
- process.android_appid = plist.uid
- AND internal_uid_package_count.uid = plist.uid
- AND (
- -- unique match
- internal_uid_package_count.cnt = 1
- -- or process name starts with the package name
- OR process.name GLOB plist.package_name || '*')
+ (
+ process.android_appid = plist.uid
+ AND internal_uid_package_count.uid = plist.uid
+ AND (
+ -- unique match
+ internal_uid_package_count.cnt = 1
+ -- or process name starts with the package name
+ OR process.name GLOB plist.package_name || '*')
+ )
+ OR
+ (
+ -- isolated processes can only be matched based on the name prefix
+ process.android_appid >= 90000 AND process.android_appid < 100000
+ AND STR_SPLIT(process.name, ':', 0) GLOB plist.package_name || '*'
+ )
);
diff --git a/src/trace_processor/stdlib/android/statsd.sql b/src/trace_processor/stdlib/android/statsd.sql
new file mode 100644
index 0000000..9ce6bf1
--- /dev/null
+++ b/src/trace_processor/stdlib/android/statsd.sql
@@ -0,0 +1,60 @@
+--
+-- Copyright 2023 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.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.
+--
+
+-- Statsd atoms.
+--
+-- A subset of the slice table containing statsd atom instant events.
+--
+-- @column id,
+-- @column type,
+-- @column ts,
+-- @column dur,
+-- @column arg_set_id,
+-- @column thread_instruction_count,
+-- @column thread_instruction_delta,
+-- @column track_id,
+-- @column category,
+-- @column name,
+-- @column depth,
+-- @column stack_id,
+-- @column parent_stack_id,
+-- @column parent_id,
+-- @column thread_ts,
+-- @column thread_dur,
+CREATE VIEW android_statsd_atoms AS
+SELECT
+ slice.id AS id,
+ slice.type AS type,
+ slice.ts AS ts,
+ slice.dur AS dur,
+ slice.arg_set_id AS arg_set_id,
+ slice.thread_instruction_count AS thread_instruction_count,
+ slice.thread_instruction_delta AS thread_instruction_delta,
+ slice.track_id AS track_id,
+ slice.category AS category,
+ slice.name AS name,
+ slice.depth AS depth,
+ slice.stack_id AS stack_id,
+ slice.parent_stack_id AS parent_stack_id,
+ slice.parent_id AS parent_id,
+ slice.thread_ts AS thread_ts,
+ slice.thread_dur AS thread_dur
+FROM slice
+JOIN track ON slice.track_id = track.id
+WHERE
+ track.name = 'Statsd Atoms';
+
+
diff --git a/src/trace_processor/stdlib/chrome/BUILD.gn b/src/trace_processor/stdlib/chrome/BUILD.gn
index b3ea475..7ba85fd 100644
--- a/src/trace_processor/stdlib/chrome/BUILD.gn
+++ b/src/trace_processor/stdlib/chrome/BUILD.gn
@@ -15,5 +15,8 @@
import("../../../../gn/perfetto_sql.gni")
perfetto_sql_source_set("chrome_sql") {
- sources = [ "cpu_powerups.sql" ]
+ sources = [
+ "chrome_scrolls.sql",
+ "cpu_powerups.sql",
+ ]
}
diff --git a/src/trace_processor/stdlib/chrome/chrome_scrolls.sql b/src/trace_processor/stdlib/chrome/chrome_scrolls.sql
new file mode 100644
index 0000000..1ad7f31
--- /dev/null
+++ b/src/trace_processor/stdlib/chrome/chrome_scrolls.sql
@@ -0,0 +1,68 @@
+-- Copyright 2023 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.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 chrome_scrolls;
+
+-- Defines slices for all of the individual scrolls in a trace based on the
+-- LatencyInfo-based scroll definition.
+--
+-- @column id The unique identifier of the scroll.
+-- @column ts The start timestamp of the scroll.
+-- @column dur The duration of the scroll.
+--
+-- NOTE: this view of top level scrolls is based on the LatencyInfo definition
+-- of a scroll, which differs subtly from the definition based on
+-- EventLatencies.
+-- TODO(b/278684408): add support for tracking scrolls across multiple Chrome/
+-- WebView instances. Currently gesture_scroll_id unique within an instance, but
+-- is not unique across multiple instances. Switching to an EventLatency based
+-- definition of scrolls should resolve this.
+CREATE VIEW chrome_scrolls AS
+WITH all_scrolls AS (
+ SELECT
+ name,
+ ts,
+ dur,
+ extract_arg(arg_set_id, 'chrome_latency_info.gesture_scroll_id') AS scroll_id
+ FROM slice
+ WHERE name GLOB 'InputLatency::GestureScroll*'
+ AND extract_arg(arg_set_id, 'chrome_latency_info.gesture_scroll_id') IS NOT NULL
+),
+scroll_starts AS (
+ SELECT
+ scroll_id,
+ MIN(ts) AS scroll_start_ts
+ FROM all_scrolls
+ WHERE name = 'InputLatency::GestureScrollBegin'
+ GROUP BY scroll_id
+), scroll_ends AS (
+ SELECT
+ scroll_id,
+ MIN(ts) AS scroll_end_ts
+ FROM all_scrolls
+ WHERE name = 'InputLatency::GestureScrollEnd'
+ GROUP BY scroll_id
+)
+SELECT
+ sa.scroll_id AS id,
+ MIN(ts) AS ts,
+ CAST(MAX(ts + dur) - MIN(ts) AS INT) AS dur,
+ IFNULL(ss.scroll_start_ts, -1) AS scroll_start_ts,
+ IFNULL(se.scroll_end_ts, -1) AS scroll_end_ts
+FROM all_scrolls sa
+ LEFT JOIN scroll_starts ss ON
+ sa.scroll_id = ss.scroll_id
+ LEFT JOIN scroll_ends se ON
+ sa.scroll_id = se.scroll_id
+GROUP BY sa.scroll_id;
\ No newline at end of file
diff --git a/src/trace_processor/tables/slice_tables.py b/src/trace_processor/tables/slice_tables.py
index 22bd9b3..f58d53d 100644
--- a/src/trace_processor/tables/slice_tables.py
+++ b/src/trace_processor/tables/slice_tables.py
@@ -11,9 +11,10 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Contains tables for relevant for TODO."""
+"""Contains tables for relevant for slices."""
from python.generators.trace_processor_table.public import Column as C
+from python.generators.trace_processor_table.public import ColumnDoc
from python.generators.trace_processor_table.public import ColumnFlag
from python.generators.trace_processor_table.public import CppInt32
from python.generators.trace_processor_table.public import CppInt64
@@ -50,23 +51,73 @@
],
wrapping_sql_view=WrappingSqlView('slice'),
tabledoc=TableDoc(
- doc='''''',
+ doc='''
+ Contains slices from userspace which explains what threads were doing
+ during the trace.
+ ''',
group='Events',
columns={
- 'ts': '''timestamp of the start of the slice (in nanoseconds)''',
- 'dur': '''duration of the slice (in nanoseconds)''',
- 'arg_set_id': '''''',
- 'thread_instruction_count': '''to the end of the slice.''',
- 'thread_instruction_delta': '''The change in value from''',
- 'track_id': '''''',
- 'category': '''''',
- 'name': '''''',
- 'depth': '''''',
- 'stack_id': '''''',
- 'parent_stack_id': '''''',
- 'parent_id': '''''',
- 'thread_ts': '''''',
- 'thread_dur': ''''''
+ 'ts':
+ 'The timestamp at the start of the slice (in nanoseconds).',
+ 'dur':
+ 'The duration of the slice (in nanoseconds).',
+ 'track_id':
+ 'The id of the track this slice is located on.',
+ 'category':
+ '''
+ The "category" of the slice. If this slice originated with
+ track_event, this column contains the category emitted.
+ Otherwise, it is likely to be null (with limited exceptions).
+ ''',
+ 'name':
+ '''
+ The name of the slice. The name describes what was happening
+ during the slice.
+ ''',
+ 'depth':
+ 'The depth of the slice in the current stack of slices.',
+ 'stack_id':
+ '''
+ A unique identifier obtained from the names of all slices
+ in this stack. This is rarely useful and kept around only
+ for legacy reasons.
+ ''',
+ 'parent_stack_id':
+ 'The stack_id for the parent of this slice. Rarely useful.',
+ 'parent_id':
+ '''
+ The id of the parent (i.e. immediate ancestor) slice for this
+ slice
+ ''',
+ 'arg_set_id':
+ ColumnDoc(
+ 'The id of the argument set associated with this slice',
+ joinable='args.arg_set_id'),
+ 'thread_ts':
+ '''
+ The thread timestamp at the start of the slice. This column
+ will only be populated if thread timestamp collection is
+ enabled with track_event.
+ ''',
+ 'thread_dur':
+ ''''
+ The thread time used by this slice. This column will only be
+ populated if thread timestamp collection is enabled with
+ track_event.
+ ''',
+ 'thread_instruction_count':
+ '''
+ The value of the CPU instruction counter at the start of the
+ slice. This column will only be populated if thread
+ instruction collection is enabled with track_event.
+ ''',
+ 'thread_instruction_delta':
+ '''
+ The change in value of the CPU instruction counter between the
+ start and end of the slice. This column will only be
+ populated if thread instruction collection is enabled with
+ track_event.
+ ''',
}))
SCHED_SLICE_TABLE = Table(
@@ -84,8 +135,8 @@
tabledoc=TableDoc(
doc='''
This table holds slices with kernel thread scheduling information.
-These slices are collected when the Linux "ftrace" data source is
-used with the "sched/switch" and "sched/wakeup*" events enabled.
+ These slices are collected when the Linux "ftrace" data source is
+ used with the "sched/switch" and "sched/wakeup*" events enabled.
''',
group='Events',
columns={
@@ -98,13 +149,16 @@
'cpu':
'''The CPU that the slice executed on.''',
'end_state':
- '''A string representing the scheduling state of the
-kernel thread at the end of the slice. The individual characters in
-the string mean the following: R (runnable), S (awaiting a wakeup),
-D (in an uninterruptible sleep), T (suspended), t (being traced),
-X (exiting), P (parked), W (waking), I (idle), N (not contributing
-to the load average), K (wakeable on fatal signals) and
-Z (zombie, awaiting cleanup).''',
+ '''
+ A string representing the scheduling state of the kernel
+ thread at the end of the slice. The individual characters in
+ the string mean the following: R (runnable), S (awaiting a
+ wakeup), D (in an uninterruptible sleep), T (suspended),
+ t (being traced), X (exiting), P (parked), W (waking),
+ I (idle), N (not contributing to the load average),
+ K (wakeable on fatal signals) and Z (zombie, awaiting
+ cleanup).
+ ''',
'priority':
'''The kernel priority that the thread ran at.'''
}))
@@ -114,27 +168,46 @@
class_name='ThreadStateTable',
sql_name='thread_state',
columns=[
- C('utid', CppUint32()),
C('ts', CppInt64()),
C('dur', CppInt64()),
C('cpu', CppOptional(CppUint32())),
+ C('utid', CppUint32()),
C('state', CppString()),
C('io_wait', CppOptional(CppUint32())),
C('blocked_function', CppOptional(CppString())),
C('waker_utid', CppOptional(CppUint32())),
],
tabledoc=TableDoc(
- doc='''''',
+ doc='''
+ This table contains the scheduling state of every thread on the
+ system during the trace. It is a subset of the |sched_slice| (sched)
+ table which only contains the times where threads were actually
+ scheduled.
+ ''',
group='Events',
columns={
- 'utid': '''''',
- 'ts': '''''',
- 'dur': '''''',
- 'cpu': '''''',
- 'state': '''''',
- 'io_wait': '''''',
- 'blocked_function': '''''',
- 'waker_utid': ''''''
+ 'ts':
+ 'The timestamp at the start of the slice (in nanoseconds).',
+ 'dur':
+ 'The duration of the slice (in nanoseconds).',
+ 'cpu':
+ '''The CPU that the slice executed on.''',
+ 'utid':
+ '''The thread's unique id in the trace..''',
+ 'state':
+ '''
+ The scheduling state of the thread. Can be "Running" or any
+ of the states described in |sched_slice.end_state|.
+ ''',
+ 'io_wait':
+ 'Indicates whether this thread was blocked on IO.',
+ 'blocked_function':
+ 'The function in the kernel this thread was blocked on.',
+ 'waker_utid':
+ '''
+ The unique thread id of the thread which caused a wakeup of
+ this thread.
+ '''
}))
GPU_SLICE_TABLE = Table(
@@ -208,7 +281,7 @@
parent=SLICE_TABLE,
tabledoc=TableDoc(
doc='''''',
- group='Misc',
+ group='Events',
columns={
'display_frame_token': '''''',
'surface_frame_token': '''''',
@@ -235,7 +308,7 @@
parent=SLICE_TABLE,
tabledoc=TableDoc(
doc='''''',
- group='Misc',
+ group='Events',
columns={
'display_frame_token': '''''',
'surface_frame_token': '''''',
@@ -265,18 +338,35 @@
C('end_bound', CppInt64(), flags=ColumnFlag.HIDDEN),
],
tabledoc=TableDoc(
- doc='''''',
+ doc='''
+ An experimental table which "flattens" stacks of slices to contain
+ only the "deepest" slice at any point in time on each track.
+ ''',
group='Misc',
columns={
- 'ts': '''''',
- 'dur': '''''',
- 'track_id': '''''',
- 'category': '''''',
- 'name': '''''',
- 'arg_set_id': '''''',
- 'source_id': '''''',
- 'start_bound': '''''',
- 'end_bound': ''''''
+ 'ts':
+ '''The timestamp at the start of the slice (in nanoseconds).''',
+ 'dur':
+ '''The duration of the slice (in nanoseconds).''',
+ 'track_id':
+ 'The id of the track this slice is located on.',
+ 'category':
+ '''
+ The "category" of the slice. If this slice originated with
+ track_event, this column contains the category emitted.
+ Otherwise, it is likely to be null (with limited exceptions).
+ ''',
+ 'name':
+ '''
+ The name of the slice. The name describes what was happening
+ during the slice.
+ ''',
+ 'arg_set_id':
+ ColumnDoc(
+ 'The id of the argument set associated with this slice',
+ joinable='args.arg_set_id'),
+ 'source_id':
+ 'The id of the slice which this row originated from.',
}))
# Keep this list sorted.
diff --git a/src/trace_processor/tp_metatrace.cc b/src/trace_processor/tp_metatrace.cc
index 79e6dbc..bf44dcf 100644
--- a/src/trace_processor/tp_metatrace.cc
+++ b/src/trace_processor/tp_metatrace.cc
@@ -24,19 +24,14 @@
using ProtoEnum = protos::pbzero::MetatraceCategories;
ProtoEnum MetatraceCategoriesToProtoEnum(MetatraceCategories categories) {
- switch (categories) {
- case MetatraceCategories::TOPLEVEL:
- return ProtoEnum::TOPLEVEL;
- case MetatraceCategories::FUNCTION:
- return ProtoEnum::FUNCTION;
- case MetatraceCategories::QUERY:
- return ProtoEnum::QUERY;
- case MetatraceCategories::ALL:
- return ProtoEnum::ALL;
- case MetatraceCategories::NONE:
- return ProtoEnum::NONE;
- }
- return ProtoEnum::NONE;
+ ProtoEnum result = ProtoEnum::NONE;
+ if (categories & MetatraceCategories::TOPLEVEL)
+ result = static_cast<ProtoEnum>(result | ProtoEnum::TOPLEVEL);
+ if (categories & MetatraceCategories::FUNCTION)
+ result = static_cast<ProtoEnum>(result | ProtoEnum::FUNCTION);
+ if (categories & MetatraceCategories::QUERY)
+ result = static_cast<ProtoEnum>(result | ProtoEnum::QUERY);
+ return result;
}
} // namespace
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 5e10fc1..f64b1c1 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -53,7 +53,7 @@
#include "src/trace_processor/prelude/functions/import.h"
#include "src/trace_processor/prelude/functions/layout_functions.h"
#include "src/trace_processor/prelude/functions/pprof_functions.h"
-#include "src/trace_processor/prelude/functions/register_function.h"
+#include "src/trace_processor/prelude/functions/sql_function.h"
#include "src/trace_processor/prelude/functions/sqlite3_str_split.h"
#include "src/trace_processor/prelude/functions/stack_functions.h"
#include "src/trace_processor/prelude/functions/to_ftrace.h"
@@ -106,13 +106,13 @@
"* FROM sqlite_temp_master)";
template <typename SqlFunction, typename Ptr = typename SqlFunction::Context*>
-void RegisterFunction(sqlite3* db,
+void RegisterFunction(SqliteEngine* engine,
const char* name,
int argc,
Ptr context = nullptr,
bool deterministic = true) {
- auto status = RegisterSqlFunction<SqlFunction>(
- db, name, argc, std::move(context), deterministic);
+ auto status = engine->RegisterSqlFunction<SqlFunction>(
+ name, argc, std::move(context), deterministic);
if (!status.ok())
PERFETTO_ELOG("%s", status.c_message());
}
@@ -238,7 +238,7 @@
}
void SetupMetrics(TraceProcessor* tp,
- sqlite3* db,
+ SqliteEngine* engine,
std::vector<metrics::SqlMetricFile>* sql_metrics,
const std::vector<std::string>& extension_paths) {
const std::vector<std::string> sanitized_extension_paths =
@@ -268,10 +268,11 @@
}
}
- RegisterFunction<metrics::NullIfEmpty>(db, "NULL_IF_EMPTY", 1);
- RegisterFunction<metrics::UnwrapMetricProto>(db, "UNWRAP_METRIC_PROTO", 2);
+ RegisterFunction<metrics::NullIfEmpty>(engine, "NULL_IF_EMPTY", 1);
+ RegisterFunction<metrics::UnwrapMetricProto>(engine, "UNWRAP_METRIC_PROTO",
+ 2);
RegisterFunction<metrics::RunMetric>(
- db, "RUN_METRIC", -1,
+ engine, "RUN_METRIC", -1,
std::unique_ptr<metrics::RunMetric::Context>(
new metrics::RunMetric::Context{tp, sql_metrics}));
@@ -279,7 +280,7 @@
// functions are supported.
{
auto ret = sqlite3_create_function_v2(
- db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr,
+ engine->db(), "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr,
metrics::RepeatedFieldStep, metrics::RepeatedFieldFinal, nullptr);
if (ret)
PERFETTO_FATAL("Error initializing RepeatedField");
@@ -454,8 +455,8 @@
}
// Register SQL functions only used in local development instances.
-void RegisterDevFunctions(sqlite3* db) {
- RegisterFunction<WriteFile>(db, "WRITE_FILE", 2);
+void RegisterDevFunctions(SqliteEngine* engine) {
+ RegisterFunction<WriteFile>(engine, "WRITE_FILE", 2);
}
sql_modules::NameToModule GetStdlibModules() {
@@ -513,38 +514,34 @@
sqlite3_str_split_init(engine_.db());
RegisterAdditionalModules(&context_);
- InitializePreludeTablesViews(engine_.db());
// New style function registration.
if (cfg.enable_dev_features) {
- RegisterDevFunctions(engine_.db());
+ RegisterDevFunctions(&engine_);
}
- RegisterFunction<Glob>(engine_.db(), "glob", 2);
- RegisterFunction<Hash>(engine_.db(), "HASH", -1);
- RegisterFunction<Base64Encode>(engine_.db(), "BASE64_ENCODE", 1);
- RegisterFunction<Demangle>(engine_.db(), "DEMANGLE", 1);
- RegisterFunction<SourceGeq>(engine_.db(), "SOURCE_GEQ", -1);
- RegisterFunction<ExportJson>(engine_.db(), "EXPORT_JSON", 1,
+ RegisterFunction<Glob>(&engine_, "glob", 2);
+ RegisterFunction<Hash>(&engine_, "HASH", -1);
+ RegisterFunction<Base64Encode>(&engine_, "BASE64_ENCODE", 1);
+ RegisterFunction<Demangle>(&engine_, "DEMANGLE", 1);
+ RegisterFunction<SourceGeq>(&engine_, "SOURCE_GEQ", -1);
+ RegisterFunction<ExportJson>(&engine_, "EXPORT_JSON", 1,
context_.storage.get(), false);
- RegisterFunction<ExtractArg>(engine_.db(), "EXTRACT_ARG", 2,
+ RegisterFunction<ExtractArg>(&engine_, "EXTRACT_ARG", 2,
context_.storage.get());
- RegisterFunction<AbsTimeStr>(engine_.db(), "ABS_TIME_STR", 1,
+ RegisterFunction<AbsTimeStr>(&engine_, "ABS_TIME_STR", 1,
context_.clock_converter.get());
- RegisterFunction<ToMonotonic>(engine_.db(), "TO_MONOTONIC", 1,
+ RegisterFunction<ToMonotonic>(&engine_, "TO_MONOTONIC", 1,
context_.clock_converter.get());
- RegisterFunction<CreateFunction>(
- engine_.db(), "CREATE_FUNCTION", 3,
- std::unique_ptr<CreateFunction::Context>(
- new CreateFunction::Context{engine_.db(), &create_function_state_}));
+ RegisterFunction<CreateFunction>(&engine_, "CREATE_FUNCTION", 3, &engine_);
RegisterFunction<CreateViewFunction>(
- engine_.db(), "CREATE_VIEW_FUNCTION", 3,
+ &engine_, "CREATE_VIEW_FUNCTION", 3,
std::unique_ptr<CreateViewFunction::Context>(
new CreateViewFunction::Context{engine_.db()}));
- RegisterFunction<Import>(engine_.db(), "IMPORT", 1,
+ RegisterFunction<Import>(&engine_, "IMPORT", 1,
std::unique_ptr<Import::Context>(new Import::Context{
engine_.db(), this, &sql_modules_}));
RegisterFunction<ToFtrace>(
- engine_.db(), "TO_FTRACE", 1,
+ &engine_, "TO_FTRACE", 1,
std::unique_ptr<ToFtrace::Context>(new ToFtrace::Context{
context_.storage.get(), SystraceSerializer(&context_)}));
@@ -554,7 +551,7 @@
RegisterLastNonNullFunction(engine_.db());
RegisterValueAtMaxTsFunction(engine_.db());
{
- base::Status status = RegisterStackFunctions(engine_.db(), &context_);
+ base::Status status = RegisterStackFunctions(&engine_, &context_);
if (!status.ok())
PERFETTO_ELOG("%s", status.c_message());
}
@@ -569,6 +566,24 @@
PERFETTO_ELOG("%s", status.c_message());
}
+ const TraceStorage* storage = context_.storage.get();
+
+ // Operator tables.
+ engine_.RegisterVirtualTableModule<SpanJoinOperatorTable>(
+ "span_join", storage, SqliteTable::TableType::kExplicitCreate, false);
+ engine_.RegisterVirtualTableModule<SpanJoinOperatorTable>(
+ "span_left_join", storage, SqliteTable::TableType::kExplicitCreate,
+ false);
+ engine_.RegisterVirtualTableModule<SpanJoinOperatorTable>(
+ "span_outer_join", storage, SqliteTable::TableType::kExplicitCreate,
+ false);
+ engine_.RegisterVirtualTableModule<WindowOperatorTable>(
+ "window", storage, SqliteTable::TableType::kExplicitCreate, true);
+ RegisterCreateViewFunctionModule(&engine_);
+
+ // Initalize the tables and views in the prelude.
+ InitializePreludeTablesViews(engine_.db());
+
auto stdlib_modules = GetStdlibModules();
for (auto module_it = stdlib_modules.GetIterator(); module_it; ++module_it) {
base::Status status =
@@ -577,18 +592,13 @@
PERFETTO_ELOG("%s", status.c_message());
}
- SetupMetrics(this, engine_.db(), &sql_metrics_,
- cfg.skip_builtin_metric_paths);
+ SetupMetrics(this, &engine_, &sql_metrics_, cfg.skip_builtin_metric_paths);
- const TraceStorage* storage = context_.storage.get();
-
- SqlStatsTable::RegisterTable(engine_.db(), storage);
- StatsTable::RegisterTable(engine_.db(), storage);
-
- // Operator tables.
- SpanJoinOperatorTable::RegisterTable(engine_.db(), storage);
- WindowOperatorTable::RegisterTable(engine_.db(), storage);
- CreateViewFunction::RegisterTable(engine_.db());
+ // Legacy tables.
+ engine_.RegisterVirtualTableModule<SqlStatsTable>(
+ "sqlstats", storage, SqliteTable::TableType::kEponymousOnly, false);
+ engine_.RegisterVirtualTableModule<StatsTable>(
+ "stats", storage, SqliteTable::TableType::kEponymousOnly, false);
// Tables dynamically generated at query time.
RegisterTableFunction(std::unique_ptr<ExperimentalFlamegraph>(
@@ -951,7 +961,7 @@
auto fn_name = desc.full_name().substr(desc.package_name().size() + 1);
std::replace(fn_name.begin(), fn_name.end(), '.', '_');
RegisterFunction<metrics::BuildProto>(
- engine_.db(), fn_name.c_str(), -1,
+ &engine_, fn_name.c_str(), -1,
std::unique_ptr<metrics::BuildProto::Context>(
new metrics::BuildProto::Context{this, &pool_, i}));
}
diff --git a/src/trace_processor/trace_processor_impl.h b/src/trace_processor/trace_processor_impl.h
index 88b4b6e..21cbd92 100644
--- a/src/trace_processor/trace_processor_impl.h
+++ b/src/trace_processor/trace_processor_impl.h
@@ -122,10 +122,6 @@
SqliteEngine engine_;
- // State necessary for CREATE_FUNCTION invocations. We store this here as we
- // need to finalize any prepared statements *before* we destroy the database.
- CreateFunction::State create_function_state_;
-
DescriptorPool pool_;
// Map from module name to module contents. Used for IMPORT function.
diff --git a/src/trace_processor/util/interned_message_view.h b/src/trace_processor/util/interned_message_view.h
index 3422b8b..f6a9a13 100644
--- a/src/trace_processor/util/interned_message_view.h
+++ b/src/trace_processor/util/interned_message_view.h
@@ -71,7 +71,9 @@
if (PERFETTO_TYPE_IDENTIFIER &&
strcmp(decoder_type_,
// GCC complains if this arg can be null.
- PERFETTO_TYPE_IDENTIFIER ? PERFETTO_TYPE_IDENTIFIER : "") != 0) {
+ static_cast<bool>(PERFETTO_TYPE_IDENTIFIER)
+ ? PERFETTO_TYPE_IDENTIFIER
+ : "") != 0) {
PERFETTO_FATAL(
"Interning entry accessed under different types! previous type: "
"%s. new type: %s.",
diff --git a/src/traced/probes/ftrace/cpu_reader_unittest.cc b/src/traced/probes/ftrace/cpu_reader_unittest.cc
index 459b640..859cc8b 100644
--- a/src/traced/probes/ftrace/cpu_reader_unittest.cc
+++ b/src/traced/probes/ftrace/cpu_reader_unittest.cc
@@ -34,6 +34,7 @@
#include "test/gtest_and_gmock.h"
#include "protos/perfetto/trace/ftrace/dpu.gen.h"
+#include "protos/perfetto/trace/ftrace/f2fs.gen.h"
#include "protos/perfetto/trace/ftrace/ftrace.gen.h"
#include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
@@ -62,6 +63,7 @@
using testing::Pair;
using testing::Property;
using testing::Return;
+using testing::SizeIs;
using testing::StartsWith;
namespace perfetto {
@@ -3303,5 +3305,113 @@
EXPECT_THAT(AllTracePackets(), IsEmpty());
}
+// Kernel code:
+// trace_f2fs_truncate_partial_nodes(... nid = {1,2,3}, depth = 4, err = 0)
+//
+// After kernel commit 0b04d4c0542e("f2fs: Fix
+// f2fs_truncate_partial_nodes ftrace event")
+static ExamplePage g_f2fs_truncate_partial_nodes_new{
+ "b281660544_new",
+ R"(
+00000000: 1555 c3e4 cb07 0000 3c00 0000 0000 0000 .U......<.......
+00000010: 3e33 0b87 2700 0000 0c00 0000 7d02 0000 >3..'.......}...
+00000020: c638 0000 3900 e00f 0000 0000 b165 0000 .8..9........e..
+00000030: 0000 0000 0100 0000 0200 0000 0300 0000 ................
+00000040: 0400 0000 0000 0000 0000 0000 0000 0000 ................
+ )",
+};
+
+TEST_F(CpuReaderParsePagePayloadTest, F2fsTruncatePartialNodesNew) {
+ const ExamplePage* test_case = &g_f2fs_truncate_partial_nodes_new;
+
+ ProtoTranslationTable* table = GetTable(test_case->name);
+ auto page = PageFromXxd(test_case->data);
+
+ FtraceDataSourceConfig ds_config = EmptyConfig();
+ ds_config.event_filter.AddEnabledEvent(table->EventToFtraceId(
+ GroupAndName("f2fs", "f2fs_truncate_partial_nodes")));
+
+ const uint8_t* parse_pos = page.get();
+ std::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_LE(parse_pos + page_header->size, page_end);
+
+ size_t evt_bytes = CpuReader::ParsePagePayload(
+ parse_pos, &page_header.value(), table, &ds_config,
+ CreateBundler(ds_config), &metadata_);
+
+ EXPECT_LT(0u, evt_bytes);
+
+ auto bundle = GetBundle();
+ ASSERT_THAT(bundle.event(), SizeIs(1));
+ auto& event = bundle.event()[0];
+ EXPECT_EQ(event.f2fs_truncate_partial_nodes().dev(), 65081u);
+ EXPECT_EQ(event.f2fs_truncate_partial_nodes().ino(), 26033u);
+ // This field is disabled in ftrace_proto_gen.cc
+ EXPECT_FALSE(event.f2fs_truncate_partial_nodes().has_nid());
+ EXPECT_EQ(event.f2fs_truncate_partial_nodes().depth(), 4);
+ EXPECT_EQ(event.f2fs_truncate_partial_nodes().err(), 0);
+}
+
+// Kernel code:
+// trace_f2fs_truncate_partial_nodes(... nid = {1,2,3}, depth = 4, err = 0)
+//
+// Before kernel commit 0b04d4c0542e("f2fs: Fix
+// f2fs_truncate_partial_nodes ftrace event")
+static ExamplePage g_f2fs_truncate_partial_nodes_old{
+ "b281660544_old",
+ R"(
+00000000: 8f90 aa0d 9e00 0000 3c00 0000 0000 0000 ........<.......
+00000010: 3e97 0295 0e01 0000 0c00 0000 7d02 0000 >...........}...
+00000020: 8021 0000 3900 e00f 0000 0000 0d66 0000 .!..9........f..
+00000030: 0000 0000 0100 0000 0200 0000 0300 0000 ................
+00000040: 0400 0000 0000 0000 0000 0000 0000 0000 ................
+ )",
+};
+
+TEST_F(CpuReaderParsePagePayloadTest, F2fsTruncatePartialNodesOld) {
+ const ExamplePage* test_case = &g_f2fs_truncate_partial_nodes_old;
+
+ ProtoTranslationTable* table = GetTable(test_case->name);
+ auto page = PageFromXxd(test_case->data);
+
+ FtraceDataSourceConfig ds_config = EmptyConfig();
+ auto id = table->EventToFtraceId(
+ GroupAndName("f2fs", "f2fs_truncate_partial_nodes"));
+ PERFETTO_LOG("Enabling: %zu", id);
+ ds_config.event_filter.AddEnabledEvent(id);
+
+ const uint8_t* parse_pos = page.get();
+ std::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_LE(parse_pos + page_header->size, page_end);
+
+ size_t evt_bytes = CpuReader::ParsePagePayload(
+ parse_pos, &page_header.value(), table, &ds_config,
+ CreateBundler(ds_config), &metadata_);
+
+ EXPECT_LT(0u, evt_bytes);
+
+ auto bundle = GetBundle();
+ ASSERT_THAT(bundle.event(), SizeIs(1));
+ auto& event = bundle.event()[0];
+ EXPECT_EQ(event.f2fs_truncate_partial_nodes().dev(), 65081u);
+ EXPECT_EQ(event.f2fs_truncate_partial_nodes().ino(), 26125u);
+ // This field is disabled in ftrace_proto_gen.cc
+ EXPECT_FALSE(event.f2fs_truncate_partial_nodes().has_nid());
+ // Due to a kernel bug, nid[1] is parsed as depth.
+ EXPECT_EQ(event.f2fs_truncate_partial_nodes().depth(), 2);
+ // Due to a kernel bug, nid[2] is parsed as err.
+ EXPECT_EQ(event.f2fs_truncate_partial_nodes().err(), 3);
+}
+
} // namespace
} // namespace perfetto
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index f17f6b6..6a8cca3 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -4266,9 +4266,6 @@
"ino", 2, ProtoSchemaType::kUint64,
TranslationStrategy::kInvalidTranslationStrategy},
{kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
- "nid", 3, ProtoSchemaType::kUint32,
- TranslationStrategy::kInvalidTranslationStrategy},
- {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
"depth", 4, ProtoSchemaType::kInt32,
TranslationStrategy::kInvalidTranslationStrategy},
{kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
diff --git a/src/traced/probes/ftrace/proto_translation_table.cc b/src/traced/probes/ftrace/proto_translation_table.cc
index 5b8c09e..9dcde14 100644
--- a/src/traced/probes/ftrace/proto_translation_table.cc
+++ b/src/traced/probes/ftrace/proto_translation_table.cc
@@ -124,7 +124,7 @@
if (!InferFtraceType(ftrace_field.type_and_name, ftrace_field.size,
ftrace_field.is_signed, &field->ftrace_type)) {
- PERFETTO_FATAL(
+ PERFETTO_DFATAL(
"Failed to infer ftrace field type for \"%s.%s\" (type:\"%s\" "
"size:%d "
"signed:%d)",
diff --git a/src/traced/probes/ftrace/test/data/b281660544_new/available_events b/src/traced/probes/ftrace/test/data/b281660544_new/available_events
new file mode 100644
index 0000000..5588a96
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/b281660544_new/available_events
@@ -0,0 +1 @@
+f2fs:f2fs_truncate_partial_nodes
diff --git a/src/traced/probes/ftrace/test/data/b281660544_new/events/f2fs/f2fs_truncate_partial_nodes/format b/src/traced/probes/ftrace/test/data/b281660544_new/events/f2fs/f2fs_truncate_partial_nodes/format
new file mode 100644
index 0000000..2f5a8ab
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/b281660544_new/events/f2fs/f2fs_truncate_partial_nodes/format
@@ -0,0 +1,15 @@
+name: f2fs_truncate_partial_nodes
+ID: 637
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:dev_t dev; offset:8; size:4; signed:0;
+ field:ino_t ino; offset:16; size:8; signed:0;
+ field:nid_t nid[3]; offset:24; size:12; signed:0;
+ field:int depth; offset:36; size:4; signed:1;
+ field:int err; offset:40; size:4; signed:1;
+
+print fmt: "dev = (%d,%d), ino = %lu, nid[0] = %u, nid[1] = %u, nid[2] = %u, depth = %d, err = %d", ((unsigned int) ((REC->dev) >> 20)), ((unsigned int) ((REC->dev) & ((1U << 20) - 1))), (unsigned long)REC->ino, (unsigned int)REC->nid[0], (unsigned int)REC->nid[1], (unsigned int)REC->nid[2], REC->depth, REC->err
diff --git a/src/traced/probes/ftrace/test/data/b281660544_new/events/header_page b/src/traced/probes/ftrace/test/data/b281660544_new/events/header_page
new file mode 100644
index 0000000..276dce9
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/b281660544_new/events/header_page
@@ -0,0 +1,4 @@
+ field: u64 timestamp; offset:0; size:8; signed:0;
+ field: local_t commit; offset:8; size:8; signed:1;
+ field: int overwrite; offset:8; size:1; signed:1;
+ field: char data; offset:16; size:4080; signed:1;
diff --git a/src/traced/probes/ftrace/test/data/b281660544_old/available_events b/src/traced/probes/ftrace/test/data/b281660544_old/available_events
new file mode 100644
index 0000000..5588a96
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/b281660544_old/available_events
@@ -0,0 +1 @@
+f2fs:f2fs_truncate_partial_nodes
diff --git a/src/traced/probes/ftrace/test/data/b281660544_old/events/f2fs/f2fs_truncate_partial_nodes/format b/src/traced/probes/ftrace/test/data/b281660544_old/events/f2fs/f2fs_truncate_partial_nodes/format
new file mode 100644
index 0000000..15f6a64
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/b281660544_old/events/f2fs/f2fs_truncate_partial_nodes/format
@@ -0,0 +1,15 @@
+name: f2fs_truncate_partial_nodes
+ID: 637
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:dev_t dev; offset:8; size:4; signed:0;
+ field:ino_t ino; offset:16; size:8; signed:0;
+ field:nid_t nid[3]; offset:24; size:4; signed:0;
+ field:int depth; offset:28; size:4; signed:1;
+ field:int err; offset:32; size:4; signed:1;
+
+print fmt: "dev = (%d,%d), ino = %lu, nid[0] = %u, nid[1] = %u, nid[2] = %u, depth = %d, err = %d", ((unsigned int) ((REC->dev) >> 20)), ((unsigned int) ((REC->dev) & ((1U << 20) - 1))), (unsigned long)REC->ino, (unsigned int)REC->nid[0], (unsigned int)REC->nid[1], (unsigned int)REC->nid[2], REC->depth, REC->err
diff --git a/src/traced/probes/ftrace/test/data/b281660544_old/events/header_page b/src/traced/probes/ftrace/test/data/b281660544_old/events/header_page
new file mode 100644
index 0000000..276dce9
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/b281660544_old/events/header_page
@@ -0,0 +1,4 @@
+ field: u64 timestamp; offset:0; size:8; signed:0;
+ field: local_t commit; offset:8; size:8; signed:1;
+ field: int overwrite; offset:8; size:1; signed:1;
+ field: char data; offset:16; size:4080; signed:1;
diff --git a/src/traced/probes/ps/process_stats_data_source.cc b/src/traced/probes/ps/process_stats_data_source.cc
index 8100e42..9ce614c 100644
--- a/src/traced/probes/ps/process_stats_data_source.cc
+++ b/src/traced/probes/ps/process_stats_data_source.cc
@@ -96,6 +96,7 @@
record_thread_names_ = cfg.record_thread_names();
dump_all_procs_on_start_ = cfg.scan_all_processes_on_start();
resolve_process_fds_ = cfg.resolve_process_fds();
+ scan_smaps_rollup_ = cfg.scan_smaps_rollup();
enable_on_demand_dumps_ = true;
for (auto quirk = cfg.quirks(); quirk; ++quirk) {
@@ -495,6 +496,11 @@
if (proc_status.empty())
continue;
+ if (scan_smaps_rollup_) {
+ std::string proc_smaps_rollup = ReadProcPidFile(pid, "smaps_rollup");
+ proc_status.append(proc_smaps_rollup);
+ }
+
if (!WriteMemCounters(pid, proc_status)) {
// If WriteMemCounters() fails the pid is very likely a kernel thread
// that has a valid /proc/[pid]/status but no memory values. In this
@@ -606,6 +612,38 @@
GetOrCreateStatsProcess(pid)->set_vm_swap_kb(counter);
cached.vm_swap_kb = counter;
}
+ // The entries below come from smaps_rollup, WriteAllProcessStats merges
+ // everything into the same buffer for convenience.
+ } else if (strcmp(key.data(), "Rss") == 0) {
+ auto counter = ToU32(value.data());
+ if (counter != cached.smr_rss_kb) {
+ GetOrCreateStatsProcess(pid)->set_smr_rss_kb(counter);
+ cached.smr_rss_kb = counter;
+ }
+ } else if (strcmp(key.data(), "Pss") == 0) {
+ auto counter = ToU32(value.data());
+ if (counter != cached.smr_pss_kb) {
+ GetOrCreateStatsProcess(pid)->set_smr_pss_kb(counter);
+ cached.smr_pss_kb = counter;
+ }
+ } else if (strcmp(key.data(), "Pss_Anon") == 0) {
+ auto counter = ToU32(value.data());
+ if (counter != cached.smr_pss_anon_kb) {
+ GetOrCreateStatsProcess(pid)->set_smr_pss_anon_kb(counter);
+ cached.smr_pss_anon_kb = counter;
+ }
+ } else if (strcmp(key.data(), "Pss_File") == 0) {
+ auto counter = ToU32(value.data());
+ if (counter != cached.smr_pss_file_kb) {
+ GetOrCreateStatsProcess(pid)->set_smr_pss_file_kb(counter);
+ cached.smr_pss_file_kb = counter;
+ }
+ } else if (strcmp(key.data(), "Pss_Shmem") == 0) {
+ auto counter = ToU32(value.data());
+ if (counter != cached.smr_pss_shmem_kb) {
+ GetOrCreateStatsProcess(pid)->set_smr_pss_shmem_kb(counter);
+ cached.smr_pss_shmem_kb = counter;
+ }
}
key.clear();
diff --git a/src/traced/probes/ps/process_stats_data_source.h b/src/traced/probes/ps/process_stats_data_source.h
index 706ee2a..4989b3c 100644
--- a/src/traced/probes/ps/process_stats_data_source.h
+++ b/src/traced/probes/ps/process_stats_data_source.h
@@ -87,6 +87,11 @@
uint32_t vm_locked_kb = std::numeric_limits<uint32_t>::max();
uint32_t vm_hvm_kb = std::numeric_limits<uint32_t>::max();
int oom_score_adj = std::numeric_limits<int>::max();
+ uint32_t smr_rss_kb = std::numeric_limits<uint32_t>::max();
+ uint32_t smr_pss_kb = std::numeric_limits<uint32_t>::max();
+ uint32_t smr_pss_anon_kb = std::numeric_limits<uint32_t>::max();
+ uint32_t smr_pss_file_kb = std::numeric_limits<uint32_t>::max();
+ uint32_t smr_pss_shmem_kb = std::numeric_limits<uint32_t>::max();
// ctime + stime from /proc/pid/stat
uint64_t cpu_time = std::numeric_limits<uint64_t>::max();
@@ -160,6 +165,7 @@
bool enable_on_demand_dumps_ = true;
bool dump_all_procs_on_start_ = false;
bool resolve_process_fds_ = false;
+ bool scan_smaps_rollup_ = false;
// This set contains PIDs as per the Linux kernel notion of a PID (which is
// really a TID). In practice this set will contain all TIDs for all processes
diff --git a/src/traced/probes/ps/process_stats_data_source_unittest.cc b/src/traced/probes/ps/process_stats_data_source_unittest.cc
index c87f0bd..5a09ebe 100644
--- a/src/traced/probes/ps/process_stats_data_source_unittest.cc
+++ b/src/traced/probes/ps/process_stats_data_source_unittest.cc
@@ -381,6 +381,10 @@
return ret.ToStdString();
}));
+ // By default scan_smaps_rollup is off and /proc/<pid>/smaps_rollup
+ // shouldn't be read.
+ EXPECT_CALL(*data_source, ReadProcPidFile(pid, "smaps_rollup")).Times(0);
+
EXPECT_CALL(*data_source, ReadProcPidFile(pid, "oom_score_adj"))
.WillRepeatedly(Invoke(
[checkpoint, kPids, &iter](int32_t inner_pid, const std::string&) {
@@ -535,5 +539,95 @@
EXPECT_THAT(nstid, ElementsAre(3));
}
+TEST_F(ProcessStatsDataSourceTest, ScanSmapsRollupIsOn) {
+ DataSourceConfig ds_config;
+ ProcessStatsConfig cfg;
+ cfg.set_proc_stats_poll_ms(1);
+ cfg.set_resolve_process_fds(true);
+ cfg.set_scan_smaps_rollup(true);
+ cfg.add_quirks(ProcessStatsConfig::DISABLE_ON_DEMAND);
+ ds_config.set_process_stats_config_raw(cfg.SerializeAsString());
+ auto data_source = GetProcessStatsDataSource(ds_config);
+
+ // Populate a fake /proc/ directory.
+ auto fake_proc = base::TempDir::Create();
+ const int kPids[] = {1, 2};
+ std::vector<std::string> dirs_to_delete;
+ for (int pid : kPids) {
+ base::StackString<256> path("%s/%d", fake_proc.path().c_str(), pid);
+ dirs_to_delete.push_back(path.ToStdString());
+ EXPECT_EQ(mkdir(path.c_str(), 0755), 0)
+ << "mkdir('" << path.c_str() << "') failed";
+ }
+
+ auto checkpoint = task_runner_.CreateCheckpoint("all_done");
+ const auto fake_proc_path = fake_proc.path();
+ EXPECT_CALL(*data_source, OpenProcDir())
+ .WillRepeatedly(Invoke([&fake_proc_path] {
+ return base::ScopedDir(opendir(fake_proc_path.c_str()));
+ }));
+ EXPECT_CALL(*data_source, GetProcMountpoint())
+ .WillRepeatedly(
+ Invoke([&fake_proc_path] { return fake_proc_path.c_str(); }));
+
+ const int kNumIters = 4;
+ int iter = 0;
+ for (int pid : kPids) {
+ EXPECT_CALL(*data_source, ReadProcPidFile(pid, "status"))
+ .WillRepeatedly(
+ Invoke([checkpoint, &iter](int32_t p, const std::string&) {
+ base::StackString<1024> ret(
+ "Name: pid_10\nVmSize: %d kB\nVmRSS:\t%d kB\n",
+ p * 100 + iter * 10 + 1, p * 100 + iter * 10 + 2);
+ return ret.ToStdString();
+ }));
+ EXPECT_CALL(*data_source, ReadProcPidFile(pid, "smaps_rollup"))
+ .WillRepeatedly(
+ Invoke([checkpoint, &iter](int32_t p, const std::string&) {
+ base::StackString<1024> ret(
+ "Name: pid_10\nRss: %d kB\nPss:\t%d kB\n",
+ p * 100 + iter * 10 + 4, p * 100 + iter * 10 + 5);
+ return ret.ToStdString();
+ }));
+
+ EXPECT_CALL(*data_source, ReadProcPidFile(pid, "oom_score_adj"))
+ .WillRepeatedly(Invoke(
+ [checkpoint, kPids, &iter](int32_t inner_pid, const std::string&) {
+ auto oom_score = inner_pid * 100 + iter * 10 + 3;
+ if (inner_pid == kPids[base::ArraySize(kPids) - 1]) {
+ if (++iter == kNumIters)
+ checkpoint();
+ }
+ return std::to_string(oom_score);
+ }));
+ }
+
+ data_source->Start();
+ task_runner_.RunUntilCheckpoint("all_done");
+ data_source->Flush(1 /* FlushRequestId */, []() {});
+
+ std::vector<protos::gen::ProcessStats::Process> processes;
+ auto trace = writer_raw_->GetAllTracePackets();
+ for (const auto& packet : trace) {
+ for (const auto& process : packet.process_stats().processes()) {
+ processes.push_back(process);
+ }
+ }
+ ASSERT_EQ(processes.size(), kNumIters * base::ArraySize(kPids));
+ iter = 0;
+ for (const auto& proc_counters : processes) {
+ int32_t pid = proc_counters.pid();
+ ASSERT_EQ(static_cast<int>(proc_counters.smr_rss_kb()),
+ pid * 100 + iter * 10 + 4);
+ ASSERT_EQ(static_cast<int>(proc_counters.smr_pss_kb()),
+ pid * 100 + iter * 10 + 5);
+ if (pid == kPids[base::ArraySize(kPids) - 1])
+ iter++;
+ }
+ for (auto path = dirs_to_delete.rbegin(); path != dirs_to_delete.rend();
+ path++)
+ base::Rmdir(*path);
+}
+
} // namespace
} // namespace perfetto
diff --git a/src/traced/probes/statsd_client/statsd_binder_data_source.cc b/src/traced/probes/statsd_client/statsd_binder_data_source.cc
index 627d4bc..9d3d7f7 100644
--- a/src/traced/probes/statsd_client/statsd_binder_data_source.cc
+++ b/src/traced/probes/statsd_client/statsd_binder_data_source.cc
@@ -242,30 +242,20 @@
const uint8_t* data,
size_t sz) {
ShellDataDecoder message(data, sz);
+ if (message.has_atom()) {
+ TraceWriter::TracePacketHandle packet = writer_->NewTracePacket();
- bool parse_error = false;
- auto timestamps_it = message.timestamp_nanos(&parse_error);
- std::vector<int64_t> timestamps;
- if (!parse_error) {
- for (; timestamps_it; ++timestamps_it) {
- timestamps.push_back(*timestamps_it);
- }
+ // The root packet gets the timestamp of *now* to aid in
+ // a) Packet sorting in trace_processor
+ // b) So we have some useful record of timestamp in case the statsd
+ // one gets broken in some exciting way.
+ packet->set_timestamp(static_cast<uint64_t>(base::GetBootTimeNs().count()));
- TraceWriter::TracePacketHandle packet;
- size_t i = 0;
- for (auto it = message.atom(); it; ++it) {
- packet = writer_->NewTracePacket();
- if (i < timestamps.size()) {
- packet->set_timestamp(static_cast<uint64_t>(timestamps[i++]));
- } else {
- packet->set_timestamp(
- static_cast<uint64_t>(base::GetBootTimeNs().count()));
- }
- auto* statsd_atom = packet->set_statsd_atom();
- auto* atom = statsd_atom->add_atom();
- atom->AppendRawProtoBytes(it->data(), it->size());
- packet->Finalize();
- }
+ // Now put all the data. We rely on ShellData and StatsdAtom
+ // matching format exactly.
+ packet->AppendBytes(protos::pbzero::TracePacket::kStatsdAtomFieldNumber,
+ message.begin(),
+ static_cast<size_t>(message.end() - message.begin()));
}
// If we have the pending flush in progress resolve that:
diff --git a/src/traced/service/BUILD.gn b/src/traced/service/BUILD.gn
index e0770db..cb142e5 100644
--- a/src/traced/service/BUILD.gn
+++ b/src/traced/service/BUILD.gn
@@ -43,6 +43,10 @@
"../../tracing/core:service",
"../../tracing/ipc/service",
]
+ if (enable_perfetto_zlib) {
+ deps += [ "../../tracing/core:zlib_compressor" ]
+ }
+
sources = [
"builtin_producer.cc",
"builtin_producer.h",
diff --git a/src/traced/service/service.cc b/src/traced/service/service.cc
index 72f19ac..c9d6335 100644
--- a/src/traced/service/service.cc
+++ b/src/traced/service/service.cc
@@ -43,6 +43,10 @@
#include <sys/system_properties.h>
#endif
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include "src/tracing/core/zlib_compressor.h"
+#endif
+
namespace perfetto {
namespace {
#if defined(PERFETTO_SET_SOCKET_PERMISSIONS)
@@ -158,7 +162,11 @@
base::UnixTaskRunner task_runner;
std::unique_ptr<ServiceIPCHost> svc;
- svc = ServiceIPCHost::CreateInstance(&task_runner);
+ TracingService::InitOpts init_opts = {};
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+ init_opts.compressor_fn = &ZlibCompressFn;
+#endif
+ svc = ServiceIPCHost::CreateInstance(&task_runner, init_opts);
// When built as part of the Android tree, the two socket are created and
// bound by init and their fd number is passed in two env variables.
diff --git a/src/tracing/core/BUILD.gn b/src/tracing/core/BUILD.gn
index ea1cb90..3fe90ea 100644
--- a/src/tracing/core/BUILD.gn
+++ b/src/tracing/core/BUILD.gn
@@ -83,6 +83,21 @@
}
}
+if (enable_perfetto_zlib) {
+ source_set("zlib_compressor") {
+ deps = [
+ ":core",
+ "../../../gn:default_deps",
+ "../../../gn:zlib",
+ "../../../include/perfetto/tracing",
+ ]
+ sources = [
+ "zlib_compressor.cc",
+ "zlib_compressor.h",
+ ]
+ }
+}
+
perfetto_unittest_source_set("unittests") {
testonly = true
deps = [
@@ -99,6 +114,14 @@
"../../base:test_support",
"../test:test_support",
]
+
+ if (enable_perfetto_zlib) {
+ deps += [
+ ":zlib_compressor",
+ "../../../gn:zlib",
+ ]
+ }
+
sources = [
"histogram_unittest.cc",
"id_allocator_unittest.cc",
@@ -110,6 +133,10 @@
"trace_packet_unittest.cc",
]
+ if (enable_perfetto_zlib) {
+ sources += [ "zlib_compressor_unittest.cc" ]
+ }
+
# These tests rely on test_task_runner.h which
# has no Windows implementation.
if (!is_win) {
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 7a15a0a..b32a658 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -16,9 +16,6 @@
#include "src/tracing/core/tracing_service_impl.h"
-#include "perfetto/base/build_config.h"
-#include "perfetto/tracing/core/forward_decls.h"
-
#include <errno.h>
#include <limits.h>
#include <string.h>
@@ -304,15 +301,18 @@
// static
std::unique_ptr<TracingService> TracingService::CreateInstance(
std::unique_ptr<SharedMemory::Factory> shm_factory,
- base::TaskRunner* task_runner) {
+ base::TaskRunner* task_runner,
+ InitOpts init_opts) {
return std::unique_ptr<TracingService>(
- new TracingServiceImpl(std::move(shm_factory), task_runner));
+ new TracingServiceImpl(std::move(shm_factory), task_runner, init_opts));
}
TracingServiceImpl::TracingServiceImpl(
std::unique_ptr<SharedMemory::Factory> shm_factory,
- base::TaskRunner* task_runner)
+ base::TaskRunner* task_runner,
+ InitOpts init_opts)
: task_runner_(task_runner),
+ init_opts_(init_opts),
shm_factory_(std::move(shm_factory)),
uid_(base::GetCurrentUserId()),
buffer_ids_(kMaxTraceBufferID),
@@ -580,8 +580,8 @@
cfg.duration_ms(), max_duration_ms);
}
- const bool has_trigger_config = cfg.trigger_config().trigger_mode() !=
- TraceConfig::TriggerConfig::UNSPECIFIED;
+ const bool has_trigger_config =
+ GetTriggerMode(cfg) != TraceConfig::TriggerConfig::UNSPECIFIED;
if (has_trigger_config &&
(cfg.trigger_config().trigger_timeout_ms() == 0 ||
cfg.trigger_config().trigger_timeout_ms() > max_duration_ms)) {
@@ -603,6 +603,16 @@
"The trace config specified an invalid trigger_mode");
}
+ if (cfg.trigger_config().use_clone_snapshot_if_available() &&
+ cfg.trigger_config().trigger_mode() !=
+ TraceConfig::TriggerConfig::STOP_TRACING) {
+ MaybeLogUploadEvent(
+ cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracingInvalidTriggerMode);
+ return PERFETTO_SVC_ERR(
+ "trigger_mode must be STOP_TRACING when "
+ "use_clone_snapshot_if_available=true");
+ }
+
if (has_trigger_config && cfg.duration_ms() != 0) {
MaybeLogUploadEvent(
cfg, uuid, PerfettoStatsdAtom::kTracedEnableTracingDurationWithTrigger);
@@ -610,8 +620,8 @@
"duration_ms was set, this must not be set for traces with triggers.");
}
- if (cfg.trigger_config().trigger_mode() ==
- TraceConfig::TriggerConfig::STOP_TRACING &&
+ if ((GetTriggerMode(cfg) == TraceConfig::TriggerConfig::STOP_TRACING ||
+ GetTriggerMode(cfg) == TraceConfig::TriggerConfig::CLONE_SNAPSHOT) &&
cfg.write_into_file()) {
// We don't support this usecase because there are subtle assumptions which
// break around TracingServiceEvents and windowed sorting (i.e. if we don't
@@ -623,8 +633,8 @@
cfg, uuid,
PerfettoStatsdAtom::kTracedEnableTracingStopTracingWriteIntoFile);
return PERFETTO_SVC_ERR(
- "Specifying trigger mode STOP_TRACING and write_into_file together is "
- "unsupported");
+ "Specifying trigger mode STOP_TRACING/CLONE_SNAPSHOT and "
+ "write_into_file together is unsupported");
}
std::unordered_set<std::string> triggers;
@@ -846,6 +856,17 @@
tracing_session->bytes_written_into_file = 0;
}
+ if (!cfg.compress_from_cli() &&
+ cfg.compression_type() == TraceConfig::COMPRESSION_TYPE_DEFLATE) {
+ if (init_opts_.compressor_fn) {
+ tracing_session->compress_deflate = true;
+ } else {
+ PERFETTO_LOG(
+ "COMPRESSION_TYPE_DEFLATE is not supported in the current build "
+ "configuration. Skipping compression");
+ }
+ }
+
// Initialize the log buffers.
bool did_allocate_all_buffers = true;
bool invalid_buffer_config = false;
@@ -936,7 +957,7 @@
bool has_start_trigger = false;
auto weak_this = weak_ptr_factory_.GetWeakPtr();
- switch (cfg.trigger_config().trigger_mode()) {
+ switch (GetTriggerMode(cfg)) {
case TraceConfig::TriggerConfig::UNSPECIFIED:
// no triggers are specified so this isn't a trace that is using triggers.
PERFETTO_DCHECK(!has_trigger_config);
@@ -953,6 +974,7 @@
cfg.trigger_config().trigger_timeout_ms());
break;
case TraceConfig::TriggerConfig::STOP_TRACING:
+ case TraceConfig::TriggerConfig::CLONE_SNAPSHOT:
// Update the tracing_session's duration_ms to ensure that if no trigger
// is received the session will end and be cleaned up equal to the
// timeout.
@@ -1238,7 +1260,7 @@
// If this trace was using STOP_TRACING triggers and we've seen
// one, then the trigger overrides the normal timeout. In this
// case we just return and let the other task clean up this trace.
- if (tracing_session_ptr->config.trigger_config().trigger_mode() ==
+ if (GetTriggerMode(tracing_session_ptr->config) ==
TraceConfig::TriggerConfig::STOP_TRACING &&
!tracing_session_ptr->received_triggers.empty())
return;
@@ -1478,7 +1500,7 @@
std::string triggered_session_name;
base::Uuid triggered_session_uuid;
TracingSessionID triggered_session_id = 0;
- int trigger_mode = 0;
+ auto trigger_mode = TraceConfig::TriggerConfig::UNSPECIFIED;
uint64_t trigger_name_hash = hash.digest();
size_t count_in_window =
@@ -1537,8 +1559,7 @@
triggered_session_name = tracing_session.config.unique_session_name();
triggered_session_uuid.set_lsb_msb(tracing_session.trace_uuid.lsb(),
tracing_session.trace_uuid.msb());
- trigger_mode = static_cast<int>(
- tracing_session.config.trigger_config().trigger_mode());
+ trigger_mode = GetTriggerMode(tracing_session.config);
const bool triggers_already_received =
!tracing_session.received_triggers.empty();
@@ -1546,7 +1567,7 @@
{static_cast<uint64_t>(now_ns), iter->name(), producer->name_,
producer->uid_});
auto weak_this = weak_ptr_factory_.GetWeakPtr();
- switch (tracing_session.config.trigger_config().trigger_mode()) {
+ switch (trigger_mode) {
case TraceConfig::TriggerConfig::START_TRACING:
// If the session has already been triggered and moved past
// CONFIGURED then we don't need to repeat StartTracing. This would
@@ -1593,6 +1614,24 @@
// will happen shortly.
iter->stop_delay_ms());
break;
+
+ case TraceConfig::TriggerConfig::CLONE_SNAPSHOT:
+ trigger_activated = true;
+ MaybeLogUploadEvent(
+ tracing_session.config, tracing_session.trace_uuid,
+ PerfettoStatsdAtom::kTracedTriggerCloneSnapshot, iter->name());
+ task_runner_->PostDelayedTask(
+ [weak_this, tsid] {
+ if (!weak_this)
+ return;
+ auto* tsess = weak_this->GetTracingSession(tsid);
+ if (!tsess || !tsess->consumer_maybe_null)
+ return;
+ tsess->consumer_maybe_null->NotifyCloneSnapshotTrigger();
+ },
+ iter->stop_delay_ms());
+ break;
+
case TraceConfig::TriggerConfig::UNSPECIFIED:
PERFETTO_ELOG("Trigger activated but trigger mode unspecified.");
break;
@@ -2299,6 +2338,8 @@
MaybeFilterPackets(tracing_session, &packets);
+ MaybeCompressPackets(tracing_session, &packets);
+
if (!*has_more) {
// We've observed some extremely high memory usage by scudo after
// MaybeFilterPackets in the past. The original bug (b/195145848) is fixed
@@ -2351,6 +2392,16 @@
}
}
+void TracingServiceImpl::MaybeCompressPackets(
+ TracingSession* tracing_session,
+ std::vector<TracePacket>* packets) {
+ if (!tracing_session->compress_deflate) {
+ return;
+ }
+
+ init_opts_.compressor_fn(packets);
+}
+
bool TracingServiceImpl::WriteIntoFile(TracingSession* tracing_session,
std::vector<TracePacket> packets) {
if (!tracing_session->write_into_file) {
@@ -3490,7 +3541,7 @@
TracingSession* session = FindTracingSessionWithMaxBugreportScore();
if (!session) {
consumer->consumer_->OnSessionCloned(
- false, "No tracing sessions eligible for bugreport found");
+ {false, "No tracing sessions eligible for bugreport found", {}});
return;
}
tsid = session->id;
@@ -3503,15 +3554,18 @@
final_flush_outcome);
if (!weak_this || !weak_consumer)
return;
- base::Status result =
- weak_this->DoCloneSession(&*weak_consumer, tsid, final_flush_outcome);
- weak_consumer->consumer_->OnSessionCloned(result.ok(), result.message());
+ base::Uuid uuid;
+ base::Status result = weak_this->DoCloneSession(&*weak_consumer, tsid,
+ final_flush_outcome, &uuid);
+ weak_consumer->consumer_->OnSessionCloned(
+ {result.ok(), result.message(), uuid});
});
}
base::Status TracingServiceImpl::DoCloneSession(ConsumerEndpointImpl* consumer,
TracingSessionID src_tsid,
- bool final_flush_outcome) {
+ bool final_flush_outcome,
+ base::Uuid* new_uuid) {
PERFETTO_DLOG("CloneSession(%" PRIu64 ") started, consumer uid: %d", src_tsid,
static_cast<int>(consumer->uid_));
@@ -3562,6 +3616,7 @@
cloned_session->state = TracingSession::CLONED_READ_ONLY;
cloned_session->trace_uuid = base::Uuidv4(); // Generate a new UUID.
+ *new_uuid = cloned_session->trace_uuid;
for (auto& kv : buf_snaps) {
BufferID buf_global_id = kv.first;
@@ -3582,6 +3637,7 @@
cloned_session->flushes_requested = src->flushes_requested;
cloned_session->flushes_succeeded = src->flushes_succeeded;
cloned_session->flushes_failed = src->flushes_failed;
+ cloned_session->compress_deflate = src->compress_deflate;
if (src->trace_filter) {
// Copy the trace filter.
cloned_session->trace_filter.reset(
@@ -3807,6 +3863,15 @@
observable_events->set_all_data_sources_started(true);
}
+void TracingServiceImpl::ConsumerEndpointImpl::NotifyCloneSnapshotTrigger() {
+ if (!(observable_events_mask_ & ObservableEvents::TYPE_CLONE_TRIGGER_HIT)) {
+ return;
+ }
+ auto* observable_events = AddObservableEvents();
+ auto* clone_trig = observable_events->mutable_clone_trigger_hit();
+ clone_trig->set_tracing_session_id(static_cast<int64_t>(tracing_session_id_));
+}
+
ObservableEvents*
TracingServiceImpl::ConsumerEndpointImpl::AddObservableEvents() {
PERFETTO_DCHECK_THREAD(thread_checker_);
@@ -3903,11 +3968,13 @@
TracingServiceCapabilities caps;
caps.set_has_query_capabilities(true);
caps.set_has_trace_config_output_path(true);
+ caps.set_has_clone_session(true);
caps.add_observable_events(ObservableEvents::TYPE_DATA_SOURCES_INSTANCES);
caps.add_observable_events(ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
- static_assert(ObservableEvents::Type_MAX ==
- ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED,
- "");
+ caps.add_observable_events(ObservableEvents::TYPE_CLONE_TRIGGER_HIT);
+ static_assert(
+ ObservableEvents::Type_MAX == ObservableEvents::TYPE_CLONE_TRIGGER_HIT,
+ "");
callback(caps);
}
diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h
index 7cefb9b..8d067fd 100644
--- a/src/tracing/core/tracing_service_impl.h
+++ b/src/tracing/core/tracing_service_impl.h
@@ -87,8 +87,9 @@
// tracing_integration_test.cc and b/195065199
// This is a rough threshold to determine how many bytes to read from the
- // buffers on each iteration when writing into a file. Since filtering
- // allocates memory, this limits the amount of memory allocated.
+ // buffers on each iteration when writing into a file. Since filtering and
+ // compression allocate memory, this effectively limits the amount of memory
+ // allocated.
static constexpr size_t kWriteIntoFileChunkSize = 1024 * 1024ul;
// The implementation behind the service endpoint exposed to each producer.
@@ -209,6 +210,7 @@
~ConsumerEndpointImpl() override;
void NotifyOnTracingDisabled(const std::string& error);
+ void NotifyCloneSnapshotTrigger();
// TracingService::ConsumerEndpoint implementation.
void EnableTracing(const TraceConfig&, base::ScopedFile) override;
@@ -264,7 +266,8 @@
};
explicit TracingServiceImpl(std::unique_ptr<SharedMemory::Factory>,
- base::TaskRunner*);
+ base::TaskRunner*,
+ InitOpts = {});
~TracingServiceImpl() override;
// Called by ProducerEndpointImpl.
@@ -565,6 +568,9 @@
// Whether we put the system info into the trace output yet.
bool did_emit_system_info = false;
+ // Whether we should compress TracePackets after reading them.
+ bool compress_deflate = false;
+
// The number of received triggers we've emitted into the trace output.
size_t num_triggers_emitted_into_trace = 0;
@@ -723,7 +729,8 @@
TraceBuffer* GetBufferByID(BufferID);
base::Status DoCloneSession(ConsumerEndpointImpl*,
TracingSessionID,
- bool final_flush_outcome);
+ bool final_flush_outcome,
+ base::Uuid*);
// Returns true if `*tracing_session` is waiting for a trigger that hasn't
// happened.
@@ -744,6 +751,10 @@
void MaybeFilterPackets(TracingSession* tracing_session,
std::vector<TracePacket>* packets);
+ // If `*tracing_session` has compression enabled, compress `*packets`.
+ void MaybeCompressPackets(TracingSession* tracing_session,
+ std::vector<TracePacket>* packets);
+
// If `*tracing_session` is configured to write into a file, writes `packets`
// into the file.
//
@@ -765,6 +776,7 @@
TracingSessionID);
base::TaskRunner* const task_runner_;
+ const InitOpts init_opts_;
std::unique_ptr<SharedMemory::Factory> shm_factory_;
ProducerID last_producer_id_ = 0;
DataSourceInstanceID last_data_source_instance_id_ = 0;
diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
index 6542723..fb175e9 100644
--- a/src/tracing/core/tracing_service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -49,6 +49,11 @@
#include "protos/perfetto/trace/trace_uuid.gen.h"
#include "protos/perfetto/trace/trigger.gen.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#include "src/tracing/core/zlib_compressor.h"
+#endif
+
using ::testing::_;
using ::testing::AssertionFailure;
using ::testing::AssertionResult;
@@ -103,6 +108,53 @@
return HasTriggerModeInternal(arg, mode);
}
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+std::string Decompress(const std::string& data) {
+ uint8_t out[1024];
+
+ z_stream stream{};
+ stream.next_in = reinterpret_cast<uint8_t*>(const_cast<char*>(data.data()));
+ stream.avail_in = static_cast<unsigned int>(data.size());
+
+ EXPECT_EQ(inflateInit(&stream), Z_OK);
+ std::string s;
+
+ int ret;
+ do {
+ stream.next_out = out;
+ stream.avail_out = sizeof(out);
+ ret = inflate(&stream, Z_NO_FLUSH);
+ EXPECT_NE(ret, Z_STREAM_ERROR);
+ EXPECT_NE(ret, Z_NEED_DICT);
+ EXPECT_NE(ret, Z_DATA_ERROR);
+ EXPECT_NE(ret, Z_MEM_ERROR);
+ s.append(reinterpret_cast<char*>(out), sizeof(out) - stream.avail_out);
+ } while (ret != Z_STREAM_END);
+
+ inflateEnd(&stream);
+ return s;
+}
+
+std::vector<protos::gen::TracePacket> DecompressTrace(
+ const std::vector<protos::gen::TracePacket> compressed) {
+ std::vector<protos::gen::TracePacket> decompressed;
+
+ for (const protos::gen::TracePacket& c : compressed) {
+ if (c.compressed_packets().empty()) {
+ decompressed.push_back(c);
+ continue;
+ }
+
+ std::string s = Decompress(c.compressed_packets());
+ protos::gen::Trace t;
+ EXPECT_TRUE(t.ParseFromString(s));
+ decompressed.insert(decompressed.end(), t.packet().begin(),
+ t.packet().end());
+ }
+ return decompressed;
+}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
} // namespace
class TracingServiceImplTest : public testing::Test {
@@ -110,11 +162,14 @@
using DataSourceInstanceState =
TracingServiceImpl::DataSourceInstance::DataSourceInstanceState;
- TracingServiceImplTest() {
+ TracingServiceImplTest() { InitializeSvcWithOpts({}); }
+
+ void InitializeSvcWithOpts(TracingService::InitOpts init_opts) {
auto shm_factory =
std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
svc.reset(static_cast<TracingServiceImpl*>(
- TracingService::CreateInstance(std::move(shm_factory), &task_runner)
+ TracingService::CreateInstance(std::move(shm_factory), &task_runner,
+ init_opts)
.release()));
svc->min_write_period_ms_ = 1;
}
@@ -1631,6 +1686,312 @@
ASSERT_EQ(6u, connect_producer_and_get_id("6"));
}
+TEST_F(TracingServiceImplTest, CompressionConfiguredButUnsupported) {
+ // Initialize the service without support for compression.
+ TracingService::InitOpts init_opts;
+ init_opts.compressor_fn = nullptr;
+ InitializeSvcWithOpts(init_opts);
+
+ std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
+ consumer->Connect(svc.get());
+
+ std::unique_ptr<MockProducer> producer = CreateMockProducer();
+ producer->Connect(svc.get(), "mock_producer");
+ producer->RegisterDataSource("data_source");
+
+ TraceConfig trace_config;
+ trace_config.add_buffers()->set_size_kb(4096);
+ auto* ds_config = trace_config.add_data_sources()->mutable_config();
+ ds_config->set_name("data_source");
+ ds_config->set_target_buffer(0);
+ // Ask for compression in the config.
+ trace_config.set_compression_type(TraceConfig::COMPRESSION_TYPE_DEFLATE);
+ consumer->EnableTracing(trace_config);
+
+ producer->WaitForTracingSetup();
+ producer->WaitForDataSourceSetup("data_source");
+ producer->WaitForDataSourceStart("data_source");
+
+ std::unique_ptr<TraceWriter> writer =
+ producer->CreateTraceWriter("data_source");
+ {
+ auto tp = writer->NewTracePacket();
+ tp->set_for_testing()->set_str("payload-1");
+ }
+ {
+ auto tp = writer->NewTracePacket();
+ tp->set_for_testing()->set_str("payload-2");
+ }
+
+ writer->Flush();
+ writer.reset();
+
+ consumer->DisableTracing();
+ producer->WaitForDataSourceStop("data_source");
+ consumer->WaitForTracingDisabled();
+
+ // The packets should NOT be compressed.
+ std::vector<protos::gen::TracePacket> packets = consumer->ReadBuffers();
+ EXPECT_THAT(packets, Not(IsEmpty()));
+ EXPECT_THAT(
+ packets,
+ Each(Property(&protos::gen::TracePacket::has_compressed_packets, false)));
+ EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str,
+ Eq("payload-1")))));
+ EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str,
+ Eq("payload-2")))));
+}
+
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+TEST_F(TracingServiceImplTest, CompressionFromCli) {
+ TracingService::InitOpts init_opts;
+ init_opts.compressor_fn = ZlibCompressFn;
+ InitializeSvcWithOpts(init_opts);
+
+ std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
+ consumer->Connect(svc.get());
+
+ std::unique_ptr<MockProducer> producer = CreateMockProducer();
+ producer->Connect(svc.get(), "mock_producer");
+ producer->RegisterDataSource("data_source");
+
+ TraceConfig trace_config;
+ trace_config.add_buffers()->set_size_kb(4096);
+ auto* ds_config = trace_config.add_data_sources()->mutable_config();
+ ds_config->set_name("data_source");
+ ds_config->set_target_buffer(0);
+ trace_config.set_compression_type(TraceConfig::COMPRESSION_TYPE_DEFLATE);
+ // When compress_from_cli is enabled, the service shouldn't do compression
+ trace_config.set_compress_from_cli(true);
+ consumer->EnableTracing(trace_config);
+
+ producer->WaitForTracingSetup();
+ producer->WaitForDataSourceSetup("data_source");
+ producer->WaitForDataSourceStart("data_source");
+
+ std::unique_ptr<TraceWriter> writer =
+ producer->CreateTraceWriter("data_source");
+ {
+ auto tp = writer->NewTracePacket();
+ tp->set_for_testing()->set_str("payload-1");
+ }
+ {
+ auto tp = writer->NewTracePacket();
+ tp->set_for_testing()->set_str("payload-2");
+ }
+
+ writer->Flush();
+ writer.reset();
+
+ consumer->DisableTracing();
+ producer->WaitForDataSourceStop("data_source");
+ consumer->WaitForTracingDisabled();
+
+ std::vector<protos::gen::TracePacket> packets = consumer->ReadBuffers();
+ EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str,
+ Eq("payload-1")))));
+ EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str,
+ Eq("payload-2")))));
+}
+
+TEST_F(TracingServiceImplTest, CompressionReadIpc) {
+ TracingService::InitOpts init_opts;
+ init_opts.compressor_fn = ZlibCompressFn;
+ InitializeSvcWithOpts(init_opts);
+
+ std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
+ consumer->Connect(svc.get());
+
+ std::unique_ptr<MockProducer> producer = CreateMockProducer();
+ producer->Connect(svc.get(), "mock_producer");
+ producer->RegisterDataSource("data_source");
+
+ TraceConfig trace_config;
+ trace_config.add_buffers()->set_size_kb(4096);
+ auto* ds_config = trace_config.add_data_sources()->mutable_config();
+ ds_config->set_name("data_source");
+ ds_config->set_target_buffer(0);
+ trace_config.set_compression_type(TraceConfig::COMPRESSION_TYPE_DEFLATE);
+ consumer->EnableTracing(trace_config);
+
+ producer->WaitForTracingSetup();
+ producer->WaitForDataSourceSetup("data_source");
+ producer->WaitForDataSourceStart("data_source");
+
+ std::unique_ptr<TraceWriter> writer =
+ producer->CreateTraceWriter("data_source");
+ {
+ auto tp = writer->NewTracePacket();
+ tp->set_for_testing()->set_str("payload-1");
+ }
+ {
+ auto tp = writer->NewTracePacket();
+ tp->set_for_testing()->set_str("payload-2");
+ }
+
+ writer->Flush();
+ writer.reset();
+
+ consumer->DisableTracing();
+ producer->WaitForDataSourceStop("data_source");
+ consumer->WaitForTracingDisabled();
+
+ std::vector<protos::gen::TracePacket> compressed_packets =
+ consumer->ReadBuffers();
+ EXPECT_THAT(compressed_packets, Not(IsEmpty()));
+ EXPECT_THAT(compressed_packets,
+ Each(Property(&protos::gen::TracePacket::compressed_packets,
+ Not(IsEmpty()))));
+ std::vector<protos::gen::TracePacket> decompressed_packets =
+ DecompressTrace(compressed_packets);
+ EXPECT_THAT(decompressed_packets,
+ Contains(Property(
+ &protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str, Eq("payload-1")))));
+ EXPECT_THAT(decompressed_packets,
+ Contains(Property(
+ &protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str, Eq("payload-2")))));
+}
+
+TEST_F(TracingServiceImplTest, CompressionWriteIntoFile) {
+ TracingService::InitOpts init_opts;
+ init_opts.compressor_fn = ZlibCompressFn;
+ InitializeSvcWithOpts(init_opts);
+
+ std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
+ consumer->Connect(svc.get());
+
+ std::unique_ptr<MockProducer> producer = CreateMockProducer();
+ producer->Connect(svc.get(), "mock_producer");
+ producer->RegisterDataSource("data_source");
+
+ TraceConfig trace_config;
+ trace_config.add_buffers()->set_size_kb(4096);
+ auto* ds_config = trace_config.add_data_sources()->mutable_config();
+ ds_config->set_name("data_source");
+ ds_config->set_target_buffer(0);
+ trace_config.set_write_into_file(true);
+ trace_config.set_compression_type(TraceConfig::COMPRESSION_TYPE_DEFLATE);
+ base::TempFile tmp_file = base::TempFile::Create();
+ consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
+
+ producer->WaitForTracingSetup();
+ producer->WaitForDataSourceSetup("data_source");
+ producer->WaitForDataSourceStart("data_source");
+
+ std::unique_ptr<TraceWriter> writer =
+ producer->CreateTraceWriter("data_source");
+ {
+ auto tp = writer->NewTracePacket();
+ tp->set_for_testing()->set_str("payload-1");
+ }
+ {
+ auto tp = writer->NewTracePacket();
+ tp->set_for_testing()->set_str("payload-2");
+ }
+
+ writer->Flush();
+ writer.reset();
+
+ consumer->DisableTracing();
+ producer->WaitForDataSourceStop("data_source");
+ consumer->WaitForTracingDisabled();
+
+ // Verify the contents of the file.
+ std::string trace_raw;
+ ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
+ protos::gen::Trace trace;
+ ASSERT_TRUE(trace.ParseFromString(trace_raw));
+ EXPECT_THAT(trace.packet(), Not(IsEmpty()));
+ EXPECT_THAT(trace.packet(),
+ Each(Property(&protos::gen::TracePacket::compressed_packets,
+ Not(IsEmpty()))));
+ std::vector<protos::gen::TracePacket> decompressed_packets =
+ DecompressTrace(trace.packet());
+ EXPECT_THAT(decompressed_packets,
+ Contains(Property(
+ &protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str, Eq("payload-1")))));
+ EXPECT_THAT(decompressed_packets,
+ Contains(Property(
+ &protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str, Eq("payload-2")))));
+}
+
+TEST_F(TracingServiceImplTest, CloneSessionWithCompression) {
+ TracingService::InitOpts init_opts;
+ init_opts.compressor_fn = ZlibCompressFn;
+ InitializeSvcWithOpts(init_opts);
+
+ // The consumer the creates the initial tracing session.
+ std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
+ consumer->Connect(svc.get());
+
+ // The consumer that clones it and reads back the data.
+ std::unique_ptr<MockConsumer> consumer2 = CreateMockConsumer();
+ consumer2->Connect(svc.get());
+
+ std::unique_ptr<MockProducer> producer = CreateMockProducer();
+ producer->Connect(svc.get(), "mock_producer");
+
+ producer->RegisterDataSource("ds_1");
+
+ TraceConfig trace_config;
+ trace_config.add_buffers()->set_size_kb(32);
+ auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
+ ds_cfg->set_name("ds_1");
+ trace_config.set_compression_type(TraceConfig::COMPRESSION_TYPE_DEFLATE);
+
+ consumer->EnableTracing(trace_config);
+ producer->WaitForTracingSetup();
+
+ producer->WaitForDataSourceSetup("ds_1");
+
+ producer->WaitForDataSourceStart("ds_1");
+
+ std::unique_ptr<TraceWriter> writer = producer->CreateTraceWriter("ds_1");
+
+ // Add some data.
+ static constexpr size_t kNumTestPackets = 20;
+ for (size_t i = 0; i < kNumTestPackets; i++) {
+ auto tp = writer->NewTracePacket();
+ std::string payload("payload" + std::to_string(i));
+ tp->set_for_testing()->set_str(payload.c_str(), payload.size());
+ tp->set_timestamp(static_cast<uint64_t>(i));
+ }
+
+ auto clone_done = task_runner.CreateCheckpoint("clone_done");
+ EXPECT_CALL(*consumer2, OnSessionCloned(_))
+ .WillOnce(Invoke([clone_done](const Consumer::OnSessionClonedArgs&) {
+ clone_done();
+ }));
+ consumer2->CloneSession(1);
+ // CloneSession() will implicitly issue a flush. Linearize with that.
+ producer->WaitForFlush(std::vector<TraceWriter*>{writer.get()});
+ task_runner.RunUntilCheckpoint("clone_done");
+
+ // Delete the initial tracing session.
+ consumer->DisableTracing();
+ consumer->FreeBuffers();
+ producer->WaitForDataSourceStop("ds_1");
+ consumer->WaitForTracingDisabled();
+
+ // Read back the cloned trace and check that it's compressed
+ std::vector<protos::gen::TracePacket> compressed_packets =
+ consumer2->ReadBuffers();
+ EXPECT_THAT(compressed_packets, Not(IsEmpty()));
+ EXPECT_THAT(compressed_packets,
+ Each(Property(&protos::gen::TracePacket::compressed_packets,
+ Not(IsEmpty()))));
+}
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
// Note: file_write_period_ms is set to a large enough to have exactly one flush
// of the tracing buffers (and therefore at most one synchronization section),
// unless the test runs unrealistically slowly, or the implementation of the
@@ -4071,7 +4432,9 @@
// Message 0: root Trace proto.
filt.AddNestedField(1 /* root trace.packet*/, 1);
filt.EndMessage();
- // Message 1: TracePacket proto. Allow only the `for_testing` sub-field.
+ // Message 1: TracePacket proto. Allow only the `for_testing` and `trace_uuid`
+ // sub-fields.
+ filt.AddSimpleField(protos::pbzero::TracePacket::kTraceUuidFieldNumber);
filt.AddSimpleField(protos::pbzero::TracePacket::kForTestingFieldNumber);
filt.EndMessage();
trace_config.mutable_trace_filter()->set_bytecode(filt.Serialize());
@@ -4100,8 +4463,17 @@
}
auto clone_done = task_runner.CreateCheckpoint("clone_done");
- EXPECT_CALL(*consumer2, OnSessionCloned(true, ""))
- .WillOnce(InvokeWithoutArgs(clone_done));
+ base::Uuid clone_uuid;
+ EXPECT_CALL(*consumer2, OnSessionCloned(_))
+ .WillOnce(Invoke(
+ [clone_done, &clone_uuid](const Consumer::OnSessionClonedArgs& args) {
+ ASSERT_TRUE(args.success);
+ ASSERT_TRUE(args.error.empty());
+ ASSERT_NE(args.uuid.msb(), 0);
+ ASSERT_NE(args.uuid.lsb(), 0);
+ clone_uuid = args.uuid;
+ clone_done();
+ }));
consumer2->CloneSession(1);
// CloneSession() will implicitly issue a flush. Linearize with that.
producer->WaitForFlush({writers[0].get(), writers[1].get()});
@@ -4145,6 +4517,16 @@
// Check that the `timestamp` field is filtered out.
EXPECT_THAT(packets,
Each(Property(&protos::gen::TracePacket::has_timestamp, false)));
+
+ // Check that the UUID in the trace matches the UUID passed to to the
+ // OnCloneSession consumer API.
+ EXPECT_THAT(
+ packets,
+ Contains(Property(
+ &protos::gen::TracePacket::trace_uuid,
+ AllOf(
+ Property(&protos::gen::TraceUuid::msb, Eq(clone_uuid.msb())),
+ Property(&protos::gen::TraceUuid::lsb, Eq(clone_uuid.lsb()))))));
}
TEST_F(TracingServiceImplTest, InvalidBufferSizes) {
diff --git a/src/tracing/core/virtual_destructors.cc b/src/tracing/core/virtual_destructors.cc
index f98d6ff..d38a776 100644
--- a/src/tracing/core/virtual_destructors.cc
+++ b/src/tracing/core/virtual_destructors.cc
@@ -38,6 +38,6 @@
// TODO(primiano): make pure virtual after various 3way patches.
void ConsumerEndpoint::CloneSession(TracingSessionID) {}
-void Consumer::OnSessionCloned(bool, const std::string&) {}
+void Consumer::OnSessionCloned(const OnSessionClonedArgs&) {}
} // namespace perfetto
diff --git a/src/tracing/core/zlib_compressor.cc b/src/tracing/core/zlib_compressor.cc
new file mode 100644
index 0000000..1a9689e
--- /dev/null
+++ b/src/tracing/core/zlib_compressor.cc
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/tracing/core/zlib_compressor.h"
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#error "Zlib must be enabled to compile this file."
+#endif
+
+#include <zlib.h>
+
+#include "protos/perfetto/trace/trace.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+
+namespace {
+
+struct Preamble {
+ uint32_t size;
+ std::array<uint8_t, 16> buf;
+};
+
+template <uint32_t id>
+Preamble GetPreamble(size_t sz) {
+ Preamble preamble;
+ uint8_t* ptr = preamble.buf.data();
+ constexpr uint32_t tag = protozero::proto_utils::MakeTagLengthDelimited(id);
+ ptr = protozero::proto_utils::WriteVarInt(tag, ptr);
+ ptr = protozero::proto_utils::WriteVarInt(sz, ptr);
+ preamble.size =
+ static_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr) -
+ reinterpret_cast<uintptr_t>(preamble.buf.data()));
+ PERFETTO_DCHECK(preamble.size < preamble.buf.size());
+ return preamble;
+}
+
+Slice PreambleToSlice(const Preamble& preamble) {
+ Slice slice = Slice::Allocate(preamble.size);
+ memcpy(slice.own_data(), preamble.buf.data(), preamble.size);
+ return slice;
+}
+
+// A compressor for `TracePacket`s that uses zlib. The class is exposed for
+// testing.
+class ZlibPacketCompressor {
+ public:
+ ZlibPacketCompressor();
+ ~ZlibPacketCompressor();
+
+ // Can be called multiple times, before Finish() is called.
+ void PushPacket(const TracePacket& packet);
+
+ // Returned the compressed data. Can be called at most once. After this call,
+ // the object is unusable (PushPacket should not be called) and must be
+ // destroyed.
+ TracePacket Finish();
+
+ private:
+ void PushData(const void* data, uint32_t size);
+ void NewOutputSlice();
+ void PushCurSlice();
+
+ z_stream stream_;
+ size_t total_new_slices_size_ = 0;
+ std::vector<Slice> new_slices_;
+ std::unique_ptr<uint8_t[]> cur_slice_;
+};
+
+ZlibPacketCompressor::ZlibPacketCompressor() {
+ memset(&stream_, 0, sizeof(stream_));
+ int status = deflateInit(&stream_, 6);
+ PERFETTO_CHECK(status == Z_OK);
+}
+
+ZlibPacketCompressor::~ZlibPacketCompressor() {
+ int status = deflateEnd(&stream_);
+ PERFETTO_CHECK(status == Z_OK);
+}
+
+void ZlibPacketCompressor::PushPacket(const TracePacket& packet) {
+ // We need to be able to tokenize packets in the compressed stream, so we
+ // prefix a proto preamble to each packet. The compressed stream looks like a
+ // valid Trace proto.
+ Preamble preamble =
+ GetPreamble<protos::pbzero::Trace::kPacketFieldNumber>(packet.size());
+ PushData(preamble.buf.data(), preamble.size);
+ for (const Slice& slice : packet.slices()) {
+ PushData(slice.start, static_cast<uint32_t>(slice.size));
+ }
+}
+
+void ZlibPacketCompressor::PushData(const void* data, uint32_t size) {
+ stream_.next_in = const_cast<Bytef*>(static_cast<const Bytef*>(data));
+ stream_.avail_in = static_cast<uInt>(size);
+ while (stream_.avail_in != 0) {
+ if (stream_.avail_out == 0) {
+ NewOutputSlice();
+ }
+ int status = deflate(&stream_, Z_NO_FLUSH);
+ PERFETTO_CHECK(status == Z_OK);
+ }
+}
+
+TracePacket ZlibPacketCompressor::Finish() {
+ for (;;) {
+ int status = deflate(&stream_, Z_FINISH);
+ if (status == Z_STREAM_END)
+ break;
+ PERFETTO_CHECK(status == Z_OK || status == Z_BUF_ERROR);
+ NewOutputSlice();
+ }
+
+ PushCurSlice();
+
+ TracePacket packet;
+ packet.AddSlice(PreambleToSlice(
+ GetPreamble<protos::pbzero::TracePacket::kCompressedPacketsFieldNumber>(
+ total_new_slices_size_)));
+ for (auto& slice : new_slices_) {
+ packet.AddSlice(std::move(slice));
+ }
+ return packet;
+}
+
+void ZlibPacketCompressor::NewOutputSlice() {
+ PushCurSlice();
+ cur_slice_ = std::make_unique<uint8_t[]>(kZlibCompressSliceSize);
+ stream_.next_out = reinterpret_cast<Bytef*>(cur_slice_.get());
+ stream_.avail_out = kZlibCompressSliceSize;
+}
+
+void ZlibPacketCompressor::PushCurSlice() {
+ if (cur_slice_) {
+ total_new_slices_size_ += kZlibCompressSliceSize - stream_.avail_out;
+ new_slices_.push_back(Slice::TakeOwnership(
+ std::move(cur_slice_), kZlibCompressSliceSize - stream_.avail_out));
+ }
+}
+
+} // namespace
+
+void ZlibCompressFn(std::vector<TracePacket>* packets) {
+ if (packets->empty()) {
+ return;
+ }
+
+ ZlibPacketCompressor stream;
+
+ for (const TracePacket& packet : *packets) {
+ stream.PushPacket(packet);
+ }
+
+ TracePacket packet = stream.Finish();
+
+ packets->clear();
+ packets->push_back(std::move(packet));
+}
+
+} // namespace perfetto
diff --git a/src/tracing/core/zlib_compressor.h b/src/tracing/core/zlib_compressor.h
new file mode 100644
index 0000000..1962c48
--- /dev/null
+++ b/src/tracing/core/zlib_compressor.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACING_CORE_ZLIB_COMPRESSOR_H_
+#define SRC_TRACING_CORE_ZLIB_COMPRESSOR_H_
+
+#include <vector>
+
+#include "perfetto/ext/tracing/core/trace_packet.h"
+
+namespace perfetto {
+
+// Matches TracingServiceImpl::kMaxTracePacketSliceSize. Exposed for testing.
+static constexpr size_t kZlibCompressSliceSize = 128 * 1024 - 512;
+
+void ZlibCompressFn(std::vector<TracePacket>*);
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_CORE_ZLIB_COMPRESSOR_H_
diff --git a/src/tracing/core/zlib_compressor_unittest.cc b/src/tracing/core/zlib_compressor_unittest.cc
new file mode 100644
index 0000000..2471c1b
--- /dev/null
+++ b/src/tracing/core/zlib_compressor_unittest.cc
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/tracing/core/zlib_compressor.h"
+
+#include <random>
+
+#include <zlib.h>
+
+#include "protos/perfetto/trace/test_event.gen.h"
+#include "protos/perfetto/trace/trace.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
+#include "src/tracing/core/tracing_service_impl.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace {
+
+using ::testing::Each;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::IsEmpty;
+using ::testing::Le;
+using ::testing::Not;
+using ::testing::Property;
+using ::testing::SizeIs;
+
+template <typename F>
+TracePacket CreateTracePacket(F fill_function) {
+ protos::gen::TracePacket msg;
+ fill_function(&msg);
+ std::vector<uint8_t> buf = msg.SerializeAsArray();
+ Slice slice = Slice::Allocate(buf.size());
+ memcpy(slice.own_data(), buf.data(), buf.size());
+ perfetto::TracePacket packet;
+ packet.AddSlice(std::move(slice));
+ return packet;
+}
+
+// Return a copy of the `old` trace packets that owns its own slices data.
+TracePacket CopyTracePacket(const TracePacket& old) {
+ TracePacket ret;
+ for (const Slice& slice : old.slices()) {
+ auto new_slice = Slice::Allocate(slice.size);
+ memcpy(new_slice.own_data(), slice.start, slice.size);
+ ret.AddSlice(std::move(new_slice));
+ }
+ return ret;
+}
+
+std::vector<TracePacket> CopyTracePackets(const std::vector<TracePacket>& old) {
+ std::vector<TracePacket> ret;
+ ret.reserve(old.size());
+ for (const TracePacket& trace_packet : old) {
+ ret.push_back(CopyTracePacket(trace_packet));
+ }
+ return ret;
+}
+std::string RandomString(size_t size) {
+ std::default_random_engine rnd(0);
+ std::uniform_int_distribution<> dist(0, 255);
+ std::string s;
+ s.resize(size);
+ for (size_t i = 0; i < s.size(); i++)
+ s[i] = static_cast<char>(dist(rnd));
+ return s;
+}
+
+std::string Decompress(const std::string& data) {
+ uint8_t out[1024];
+
+ z_stream stream{};
+ stream.next_in = reinterpret_cast<uint8_t*>(const_cast<char*>(data.data()));
+ stream.avail_in = static_cast<unsigned int>(data.size());
+
+ EXPECT_EQ(inflateInit(&stream), Z_OK);
+ std::string s;
+
+ int ret;
+ do {
+ stream.next_out = out;
+ stream.avail_out = sizeof(out);
+ ret = inflate(&stream, Z_NO_FLUSH);
+ EXPECT_NE(ret, Z_STREAM_ERROR);
+ EXPECT_NE(ret, Z_NEED_DICT);
+ EXPECT_NE(ret, Z_DATA_ERROR);
+ EXPECT_NE(ret, Z_MEM_ERROR);
+ s.append(reinterpret_cast<char*>(out), sizeof(out) - stream.avail_out);
+ } while (ret != Z_STREAM_END);
+
+ inflateEnd(&stream);
+ return s;
+}
+
+static_assert(kZlibCompressSliceSize ==
+ TracingServiceImpl::kMaxTracePacketSliceSize);
+
+TEST(ZlibCompressFnTest, Empty) {
+ std::vector<TracePacket> packets;
+
+ ZlibCompressFn(&packets);
+
+ EXPECT_THAT(packets, IsEmpty());
+}
+
+TEST(ZlibCompressFnTest, End2EndCompressAndDecompress) {
+ std::vector<TracePacket> packets;
+
+ packets.push_back(CreateTracePacket([](protos::gen::TracePacket* msg) {
+ auto* for_testing = msg->mutable_for_testing();
+ for_testing->set_str("abc");
+ }));
+ packets.push_back(CreateTracePacket([](protos::gen::TracePacket* msg) {
+ auto* for_testing = msg->mutable_for_testing();
+ for_testing->set_str("def");
+ }));
+
+ ZlibCompressFn(&packets);
+
+ ASSERT_THAT(packets, SizeIs(1));
+ protos::gen::TracePacket compressed_packet_proto;
+ ASSERT_TRUE(compressed_packet_proto.ParseFromString(
+ packets[0].GetRawBytesForTesting()));
+ const std::string& data = compressed_packet_proto.compressed_packets();
+ EXPECT_THAT(data, Not(IsEmpty()));
+ protos::gen::Trace subtrace;
+ ASSERT_TRUE(subtrace.ParseFromString(Decompress(data)));
+ EXPECT_THAT(
+ subtrace.packet(),
+ ElementsAre(Property(&protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str, "abc")),
+ Property(&protos::gen::TracePacket::for_testing,
+ Property(&protos::gen::TestEvent::str, "def"))));
+}
+
+TEST(ZlibCompressFnTest, MaxSliceSize) {
+ std::vector<TracePacket> packets;
+
+ constexpr size_t kStopOutputSize =
+ TracingServiceImpl::kMaxTracePacketSliceSize + 2000;
+
+ TracePacket compressed_packet;
+ while (compressed_packet.size() < kStopOutputSize) {
+ packets.push_back(CreateTracePacket([](protos::gen::TracePacket* msg) {
+ auto* for_testing = msg->mutable_for_testing();
+ for_testing->set_str(RandomString(65536));
+ }));
+ {
+ std::vector<TracePacket> packets_copy = CopyTracePackets(packets);
+ ZlibCompressFn(&packets_copy);
+ ASSERT_THAT(packets_copy, SizeIs(1));
+ compressed_packet = std::move(packets_copy[0]);
+ }
+ }
+
+ EXPECT_GE(compressed_packet.slices().size(), 2u);
+ ASSERT_GT(compressed_packet.size(),
+ TracingServiceImpl::kMaxTracePacketSliceSize);
+ EXPECT_THAT(compressed_packet.slices(),
+ Each(Field(&Slice::size,
+ Le(TracingServiceImpl::kMaxTracePacketSliceSize))));
+}
+
+} // namespace
+} // namespace perfetto
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index 181237f..5169a2b 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -644,8 +644,7 @@
}
void TracingMuxerImpl::ConsumerImpl::OnSessionCloned(
- bool /*success*/,
- const std::string& /*error*/) {
+ const OnSessionClonedArgs&) {
// CloneSession is not exposed in the SDK. This should never happen.
PERFETTO_DCHECK(false);
}
@@ -1165,7 +1164,8 @@
}
// Only allow certain interceptors for now.
if (descriptor.name() != "test_interceptor" &&
- descriptor.name() != "console") {
+ descriptor.name() != "console" &&
+ descriptor.name() != "etwexport") {
PERFETTO_ELOG(
"Interceptors are experimental. If you want to use them, please "
"get in touch with the project maintainers "
diff --git a/src/tracing/internal/tracing_muxer_impl.h b/src/tracing/internal/tracing_muxer_impl.h
index 4c87bb9..54d2fc3 100644
--- a/src/tracing/internal/tracing_muxer_impl.h
+++ b/src/tracing/internal/tracing_muxer_impl.h
@@ -300,7 +300,7 @@
void OnAttach(bool success, const TraceConfig&) override;
void OnTraceStats(bool success, const TraceStats&) override;
void OnObservableEvents(const ObservableEvents&) override;
- void OnSessionCloned(bool, const std::string&) override;
+ void OnSessionCloned(const OnSessionClonedArgs&) override;
void NotifyStartComplete();
void NotifyError(const TracingError&);
diff --git a/src/tracing/internal/tracing_muxer_impl_integrationtest.cc b/src/tracing/internal/tracing_muxer_impl_integrationtest.cc
index 5711d73..bc28cde 100644
--- a/src/tracing/internal/tracing_muxer_impl_integrationtest.cc
+++ b/src/tracing/internal/tracing_muxer_impl_integrationtest.cc
@@ -25,6 +25,12 @@
class TracingMuxerImplIntegrationTest : public testing::Test {
protected:
+ void SetUp() override {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ GTEST_SKIP() << "Unix sockets not supported on windows";
+#endif
+ }
+
// Sets the environment variable `name` to `value`. Restores it to the
// previous value when the test finishes.
void SetEnvVar(const char* name, const char* value) {
@@ -38,7 +44,7 @@
base::SetEnv(name, value);
}
- ~TracingMuxerImplIntegrationTest() {
+ ~TracingMuxerImplIntegrationTest() override {
perfetto::Tracing::ResetForTesting();
while (!prev_state_.empty()) {
const EnvVar& var = prev_state_.top();
diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
index 7eecd09..cf34361 100644
--- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
+++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
@@ -479,10 +479,11 @@
// If the IPC fails, we are talking to an older version of the service
// that didn't support CloneSession at all.
weak_this->consumer_->OnSessionCloned(
- false, "CloneSession IPC not supported");
+ {false, "CloneSession IPC not supported", {}});
} else {
- weak_this->consumer_->OnSessionCloned(response->success(),
- response->error());
+ base::Uuid uuid(response->uuid_lsb(), response->uuid_msb());
+ weak_this->consumer_->OnSessionCloned(
+ {response->success(), response->error(), uuid});
}
});
consumer_port_.CloneSession(req, std::move(async_response));
diff --git a/src/tracing/ipc/service/consumer_ipc_service.cc b/src/tracing/ipc/service/consumer_ipc_service.cc
index 2f45713..ac52864 100644
--- a/src/tracing/ipc/service/consumer_ipc_service.cc
+++ b/src/tracing/ipc/service/consumer_ipc_service.cc
@@ -480,14 +480,15 @@
}
void ConsumerIPCService::RemoteConsumer::OnSessionCloned(
- bool success,
- const std::string& error) {
+ const OnSessionClonedArgs& args) {
if (!clone_session_response.IsBound())
return;
auto resp = ipc::AsyncResult<protos::gen::CloneSessionResponse>::Create();
- resp->set_success(success);
- resp->set_error(error);
+ resp->set_success(args.success);
+ resp->set_error(args.error);
+ resp->set_uuid_msb(args.uuid.msb());
+ resp->set_uuid_lsb(args.uuid.lsb());
std::move(clone_session_response).Resolve(std::move(resp));
}
diff --git a/src/tracing/ipc/service/consumer_ipc_service.h b/src/tracing/ipc/service/consumer_ipc_service.h
index d570c51..f1424d9 100644
--- a/src/tracing/ipc/service/consumer_ipc_service.h
+++ b/src/tracing/ipc/service/consumer_ipc_service.h
@@ -94,7 +94,7 @@
void OnAttach(bool, const TraceConfig&) override;
void OnTraceStats(bool, const TraceStats&) override;
void OnObservableEvents(const ObservableEvents&) override;
- void OnSessionCloned(bool, const std::string&) override;
+ void OnSessionCloned(const OnSessionClonedArgs&) override;
void CloseObserveEventsResponseStream();
diff --git a/src/tracing/ipc/service/service_ipc_host_impl.cc b/src/tracing/ipc/service/service_ipc_host_impl.cc
index 85029a2..1df674e 100644
--- a/src/tracing/ipc/service/service_ipc_host_impl.cc
+++ b/src/tracing/ipc/service/service_ipc_host_impl.cc
@@ -40,12 +40,15 @@
// Implements the publicly exposed factory method declared in
// include/tracing/posix_ipc/posix_service_host.h.
std::unique_ptr<ServiceIPCHost> ServiceIPCHost::CreateInstance(
- base::TaskRunner* task_runner) {
- return std::unique_ptr<ServiceIPCHost>(new ServiceIPCHostImpl(task_runner));
+ base::TaskRunner* task_runner,
+ TracingService::InitOpts init_opts) {
+ return std::unique_ptr<ServiceIPCHost>(
+ new ServiceIPCHostImpl(task_runner, init_opts));
}
-ServiceIPCHostImpl::ServiceIPCHostImpl(base::TaskRunner* task_runner)
- : task_runner_(task_runner) {}
+ServiceIPCHostImpl::ServiceIPCHostImpl(base::TaskRunner* task_runner,
+ TracingService::InitOpts init_opts)
+ : task_runner_(task_runner), init_opts_(init_opts) {}
ServiceIPCHostImpl::~ServiceIPCHostImpl() {}
@@ -95,7 +98,8 @@
std::unique_ptr<SharedMemory::Factory> shm_factory(
new PosixSharedMemory::Factory());
#endif
- svc_ = TracingService::CreateInstance(std::move(shm_factory), task_runner_);
+ svc_ = TracingService::CreateInstance(std::move(shm_factory), task_runner_,
+ init_opts_);
if (!producer_ipc_port_ || !consumer_ipc_port_) {
Shutdown();
diff --git a/src/tracing/ipc/service/service_ipc_host_impl.h b/src/tracing/ipc/service/service_ipc_host_impl.h
index dda7e5b..4ccfa65 100644
--- a/src/tracing/ipc/service/service_ipc_host_impl.h
+++ b/src/tracing/ipc/service/service_ipc_host_impl.h
@@ -33,7 +33,8 @@
// producer_ipc_service.cc and consumer_ipc_service.cc.
class ServiceIPCHostImpl : public ServiceIPCHost {
public:
- ServiceIPCHostImpl(base::TaskRunner*);
+ explicit ServiceIPCHostImpl(base::TaskRunner*,
+ TracingService::InitOpts init_opts = {});
~ServiceIPCHostImpl() override;
// ServiceIPCHost implementation.
@@ -51,6 +52,7 @@
void Shutdown();
base::TaskRunner* const task_runner_;
+ const TracingService::InitOpts init_opts_;
std::unique_ptr<TracingService> svc_; // The service business logic.
// The IPC host that listens on the Producer socket. It owns the
diff --git a/src/tracing/test/mock_consumer.h b/src/tracing/test/mock_consumer.h
index 3b6ad2b..2253d93 100644
--- a/src/tracing/test/mock_consumer.h
+++ b/src/tracing/test/mock_consumer.h
@@ -83,7 +83,7 @@
MOCK_METHOD(void, OnAttach, (bool, const TraceConfig&), (override));
MOCK_METHOD(void, OnTraceStats, (bool, const TraceStats&), (override));
MOCK_METHOD(void, OnObservableEvents, (const ObservableEvents&), (override));
- MOCK_METHOD(void, OnSessionCloned, (bool, const std::string&), (override));
+ MOCK_METHOD(void, OnSessionCloned, (const OnSessionClonedArgs&), (override));
// gtest doesn't support move-only types. This wrapper is here jut to pass
// a pointer to the vector (rather than the vector itself) to the mock method.
diff --git a/src/tracing/test/tracing_integration_test.cc b/src/tracing/test/tracing_integration_test.cc
index 05fa126..29949a8 100644
--- a/src/tracing/test/tracing_integration_test.cc
+++ b/src/tracing/test/tracing_integration_test.cc
@@ -97,7 +97,7 @@
MOCK_METHOD(void, OnAttach, (bool, const TraceConfig&), (override));
MOCK_METHOD(void, OnTraceStats, (bool, const TraceStats&), (override));
MOCK_METHOD(void, OnObservableEvents, (const ObservableEvents&), (override));
- MOCK_METHOD(void, OnSessionCloned, (bool, const std::string&), (override));
+ MOCK_METHOD(void, OnSessionCloned, (const OnSessionClonedArgs&), (override));
// Workaround, gmock doesn't support yet move-only types, passing a pointer.
void OnTraceData(std::vector<TracePacket> packets, bool has_more) {
diff --git a/test/cmdline_integrationtest.cc b/test/cmdline_integrationtest.cc
index cbc3555..f8c7a43 100644
--- a/test/cmdline_integrationtest.cc
+++ b/test/cmdline_integrationtest.cc
@@ -46,6 +46,7 @@
using ::testing::ContainsRegex;
using ::testing::Each;
using ::testing::ElementsAreArray;
+using ::testing::Eq;
using ::testing::HasSubstr;
using ::testing::Property;
using ::testing::SizeIs;
@@ -80,6 +81,13 @@
return trace_config;
}
+class ScopedFileRemove {
+ public:
+ explicit ScopedFileRemove(const std::string& path) : path_(path) {}
+ ~ScopedFileRemove() { remove(path_.c_str()); }
+ std::string path_;
+};
+
class PerfettoCmdlineTest : public ::testing::Test {
public:
void SetUp() override {
@@ -137,8 +145,10 @@
// This is in common to the 3 TEST_F SaveForBugreport* fixtures, which differ
// only in the config, passed here as input.
void RunBugreportTest(protos::gen::TraceConfig trace_config,
- bool check_original_trace = true) {
+ bool check_original_trace = true,
+ bool use_explicit_clone = false) {
const std::string path = RandomTraceFileName();
+ ScopedFileRemove remove_on_test_exit(path);
auto perfetto_proc = ExecPerfetto(
{
@@ -149,9 +159,10 @@
},
trace_config.SerializeAsString());
- auto perfetto_br_proc = ExecPerfetto({
- "--save-for-bugreport",
- });
+ Exec perfetto_br_proc =
+ use_explicit_clone
+ ? ExecPerfetto({"--out", GetBugreportTracePath(), "--clone", "-1"})
+ : ExecPerfetto({"--save-for-bugreport"});
// Start the service and connect a simple fake producer.
StartServiceIfRequiredNoNewExecsAfterThis();
@@ -364,6 +375,7 @@
// (could deadlock) to fork after we've spawned some threads which might
// printf (and thus hold locks).
const std::string path = RandomTraceFileName();
+ ScopedFileRemove remove_on_test_exit(path);
auto perfetto_proc = ExecPerfetto(
{
"-o",
@@ -458,6 +470,7 @@
// (could deadlock) to fork after we've spawned some threads which might
// printf (and thus hold locks).
const std::string path = RandomTraceFileName();
+ ScopedFileRemove remove_on_test_exit(path);
auto perfetto_proc = ExecPerfetto(
{
"-o",
@@ -562,6 +575,7 @@
// (could deadlock) to fork after we've spawned some threads which might
// printf (and thus hold locks).
const std::string path = RandomTraceFileName();
+ ScopedFileRemove remove_on_test_exit(path);
auto perfetto_proc = ExecPerfetto(
{
"--dropbox",
@@ -616,6 +630,7 @@
// (could deadlock) to fork after we've spawned some threads which might
// printf (and thus hold locks).
const std::string path = RandomTraceFileName();
+ ScopedFileRemove remove_on_test_exit(path);
auto perfetto_proc = ExecPerfetto(
{
"-o",
@@ -719,6 +734,7 @@
// (could deadlock) to fork after we've spawned some threads which might
// printf (and thus hold locks).
const std::string path = RandomTraceFileName();
+ ScopedFileRemove remove_on_test_exit(path);
std::string triggers = R"(
activate_triggers: "trigger_name_2"
activate_triggers: "trigger_name"
@@ -782,6 +798,7 @@
// (could deadlock) to fork after we've spawned some threads which might
// printf (and thus hold locks).
const std::string path = RandomTraceFileName();
+ ScopedFileRemove remove_on_test_exit(path);
auto perfetto_proc = ExecPerfetto(
{
"-o",
@@ -829,11 +846,100 @@
protos::gen::Trace trace;
ASSERT_TRUE(trace.ParseFromString(trace_str));
EXPECT_LT(static_cast<int>(kMessageCount), trace.packet_size());
- for (const auto& packet : trace.packet()) {
- if (packet.has_trigger()) {
- EXPECT_EQ("trigger_name", packet.trigger().trigger_name());
- }
+ EXPECT_THAT(trace.packet(),
+ Contains(Property(&protos::gen::TracePacket::trigger,
+ Property(&protos::gen::Trigger::trigger_name,
+ Eq("trigger_name")))));
+}
+
+TEST_F(PerfettoCmdlineTest, TriggerCloneSnapshot) {
+ constexpr size_t kMessageCount = 2;
+ constexpr size_t kMessageSize = 2;
+ protos::gen::TraceConfig trace_config;
+ trace_config.add_buffers()->set_size_kb(1024);
+ auto* ds_config = trace_config.add_data_sources()->mutable_config();
+ ds_config->set_name("android.perfetto.FakeProducer");
+ ds_config->mutable_for_testing()->set_message_count(kMessageCount);
+ ds_config->mutable_for_testing()->set_message_size(kMessageSize);
+ auto* trigger_cfg = trace_config.mutable_trigger_config();
+ trigger_cfg->set_trigger_mode(
+ protos::gen::TraceConfig::TriggerConfig::CLONE_SNAPSHOT);
+ trigger_cfg->set_trigger_timeout_ms(600000);
+ auto* trigger = trigger_cfg->add_triggers();
+ trigger->set_name("trigger_name");
+ // |stop_delay_ms| must be long enough that we can write the packets in
+ // before the trace finishes. This has to be long enough for the slowest
+ // emulator. But as short as possible to prevent the test running a long
+ // time.
+ trigger->set_stop_delay_ms(500);
+
+ // We have to construct all the processes we want to fork before we start the
+ // service with |StartServiceIfRequired()|. this is because it is unsafe
+ // (could deadlock) to fork after we've spawned some threads which might
+ // printf (and thus hold locks).
+ const std::string path = RandomTraceFileName();
+ ScopedFileRemove remove_on_test_exit(path);
+ auto perfetto_proc = ExecPerfetto(
+ {
+ "-o",
+ path,
+ "-c",
+ "-",
+ },
+ trace_config.SerializeAsString());
+
+ std::string triggers = R"(
+ activate_triggers: "trigger_name"
+ )";
+ auto trigger_proc = ExecPerfetto(
+ {
+ "-c",
+ "-",
+ "--txt",
+ },
+ triggers);
+
+ // Start the service and connect a simple fake producer.
+ StartServiceIfRequiredNoNewExecsAfterThis();
+ auto* fake_producer = ConnectFakeProducer();
+ EXPECT_TRUE(fake_producer);
+
+ std::thread background_trace([&perfetto_proc]() {
+ std::string stderr_str;
+ EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
+ });
+
+ WaitForProducerEnabled();
+ // Wait for the producer to start, and then write out 11 packets, before the
+ // trace actually starts (the trigger is seen).
+ auto on_data_written = task_runner_.CreateCheckpoint("data_written_1");
+ fake_producer->ProduceEventBatch(WrapTask(on_data_written));
+ task_runner_.RunUntilCheckpoint("data_written_1");
+
+ EXPECT_EQ(0, trigger_proc.Run(&stderr_)) << "stderr: " << stderr_;
+
+ // Now we need to wait that the `perfetto_proc` creates the snapshot trace
+ // file in the trace/path.0 file (appending .0). Once that is done we can
+ // kill the perfetto cmd (otherwise it will keep running for the whole
+ // trigger_timeout_ms, unlike the case of STOP_TRACING.
+ std::string snapshot_path = path + ".0";
+ for (int i = 0; i < 100 && !base::FileExists(snapshot_path); i++) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
+ ASSERT_TRUE(base::FileExists(snapshot_path));
+
+ perfetto_proc.SendSigterm();
+ background_trace.join();
+
+ std::string trace_str;
+ base::ReadFile(snapshot_path, &trace_str);
+ protos::gen::Trace trace;
+ ASSERT_TRUE(trace.ParseFromString(trace_str));
+ EXPECT_LT(static_cast<int>(kMessageCount), trace.packet_size());
+ EXPECT_THAT(trace.packet(),
+ Contains(Property(&protos::gen::TracePacket::trigger,
+ Property(&protos::gen::Trigger::trigger_name,
+ Eq("trigger_name")))));
}
TEST_F(PerfettoCmdlineTest, SaveForBugreport) {
@@ -848,6 +954,21 @@
RunBugreportTest(std::move(trace_config));
}
+TEST_F(PerfettoCmdlineTest, Clone) {
+ TraceConfig trace_config = CreateTraceConfigForBugreportTest();
+ RunBugreportTest(std::move(trace_config), /*check_original_trace=*/true,
+ /*use_explicit_clone=*/true);
+}
+
+// Regression test for b/279753347 .
+TEST_F(PerfettoCmdlineTest, UnavailableBugreportLeavesNoEmptyFiles) {
+ ScopedFileRemove remove_on_test_exit(GetBugreportTracePath());
+ Exec perfetto_br_proc = ExecPerfetto({"--save-for-bugreport"});
+ StartServiceIfRequiredNoNewExecsAfterThis();
+ perfetto_br_proc.Run(&stderr_);
+ ASSERT_FALSE(base::FileExists(GetBugreportTracePath()));
+}
+
// 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 .
diff --git a/test/configs/BUILD.gn b/test/configs/BUILD.gn
index 230fe01..b56822b 100644
--- a/test/configs/BUILD.gn
+++ b/test/configs/BUILD.gn
@@ -40,6 +40,7 @@
"long_trace.cfg",
"mm_events.cfg",
"scheduling.cfg",
+ "snapshot.cfg",
"summary.cfg",
"sys_stats.cfg",
"thermal.cfg",
diff --git a/test/configs/snapshot.cfg b/test/configs/snapshot.cfg
new file mode 100644
index 0000000..eb2c197
--- /dev/null
+++ b/test/configs/snapshot.cfg
@@ -0,0 +1,49 @@
+unique_session_name: "test_snap"
+
+buffers {
+ size_kb: 32768
+ fill_policy: RING_BUFFER
+}
+
+# Enable various data sources as usual.
+data_sources {
+ config {
+ name: "linux.ftrace"
+ target_buffer: 0
+ ftrace_config {
+ ftrace_events: "cpu_frequency"
+ ftrace_events: "cpu_idle"
+ ftrace_events: "sched_process_exec"
+ ftrace_events: "sched_process_exit"
+ ftrace_events: "sched_process_fork"
+ ftrace_events: "sched_process_free"
+ ftrace_events: "sched_process_hang"
+ ftrace_events: "sched_process_wait"
+ ftrace_events: "sched_switch"
+ ftrace_events: "sched_wakeup_new"
+ ftrace_events: "sched_wakeup"
+ ftrace_events: "sched_waking"
+ ftrace_events: "task_newtask"
+ ftrace_events: "task_rename"
+ ftrace_events: "tracing_mark_write"
+ }
+ }
+}
+
+data_sources {
+ config {
+ name: "linux.process_stats"
+ target_buffer: 0
+ }
+}
+
+
+trigger_config {
+ trigger_mode: STOP_TRACING
+ use_clone_snapshot_if_available: true
+ trigger_timeout_ms: 300000
+ triggers {
+ name: "xxx"
+ stop_delay_ms: 0
+ }
+}
diff --git a/test/cts/reporter/reporter_test_cts.cc b/test/cts/reporter/reporter_test_cts.cc
index f9294f4..f27d3da 100644
--- a/test/cts/reporter/reporter_test_cts.cc
+++ b/test/cts/reporter/reporter_test_cts.cc
@@ -42,6 +42,7 @@
trace_config.add_buffers()->set_size_kb(1024);
trace_config.set_duration_ms(200);
trace_config.set_allow_user_build_tracing(true);
+ trace_config.set_unique_session_name("TestEndToEndReport");
auto* ds_config = trace_config.add_data_sources()->mutable_config();
ds_config->set_name("android.perfetto.FakeProducer");
@@ -72,6 +73,7 @@
auto perfetto_proc = Exec("perfetto",
{
"--upload",
+ "--no-guardrails",
"-c",
"-",
},
diff --git a/test/data/ui-screenshots/ui-android_trace_30s_expand_camera.png.sha256 b/test/data/ui-screenshots/ui-android_trace_30s_expand_camera.png.sha256
index 2dc02a8..adfa483 100644
--- a/test/data/ui-screenshots/ui-android_trace_30s_expand_camera.png.sha256
+++ b/test/data/ui-screenshots/ui-android_trace_30s_expand_camera.png.sha256
@@ -1 +1 @@
-7f615abbabf2f257db5e2da2053ee6549f078b29d3bd87cf57d7881c04d22308
\ No newline at end of file
+37ce86e92a72fe05c24acfcadf1393f3407a99e3dcdda6b3c883f380ffd00b41
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-android_trace_30s_load.png.sha256 b/test/data/ui-screenshots/ui-android_trace_30s_load.png.sha256
index 7d33dac..ba42f34 100644
--- a/test/data/ui-screenshots/ui-android_trace_30s_load.png.sha256
+++ b/test/data/ui-screenshots/ui-android_trace_30s_load.png.sha256
@@ -1 +1 @@
-7094972e62950d148cdcbb3a0d707d2e3d90e199dccd104a40ce080c7dfdd4c3
\ No newline at end of file
+0c7f3705f1d29c0b16756b66cb748635352fef3928a173b34d995356e6d3d58e
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-chrome_missing_track_names_load.png.sha256 b/test/data/ui-screenshots/ui-chrome_missing_track_names_load.png.sha256
index 43cc894..4c65000 100644
--- a/test/data/ui-screenshots/ui-chrome_missing_track_names_load.png.sha256
+++ b/test/data/ui-screenshots/ui-chrome_missing_track_names_load.png.sha256
@@ -1 +1 @@
-4d4df6ae3544a729179237404c9ac89c55857bc729e6b6a94f2ede8909a3c0ba
\ No newline at end of file
+c8277a777519e7c1bf762d4e0e299a79a66da88ce54ed26e6d27939dca6128c9
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-chrome_rendering_desktop_expand_browser_proc.png.sha256 b/test/data/ui-screenshots/ui-chrome_rendering_desktop_expand_browser_proc.png.sha256
index 30d331e..f504faf 100644
--- a/test/data/ui-screenshots/ui-chrome_rendering_desktop_expand_browser_proc.png.sha256
+++ b/test/data/ui-screenshots/ui-chrome_rendering_desktop_expand_browser_proc.png.sha256
@@ -1 +1 @@
-d54629320958188baccd6318abac1118c52ac25356ffb564197db10915bbdfb7
\ No newline at end of file
+dc246b0bf68834a63464c0c98e35a060cb3698947084cdb9d976207a37bf8156
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-chrome_rendering_desktop_load.png.sha256 b/test/data/ui-screenshots/ui-chrome_rendering_desktop_load.png.sha256
index fc808f9..0ee6b17 100644
--- a/test/data/ui-screenshots/ui-chrome_rendering_desktop_load.png.sha256
+++ b/test/data/ui-screenshots/ui-chrome_rendering_desktop_load.png.sha256
@@ -1 +1 @@
-4858f2f153f5e711ab84edc953bb68a819bf6e1fde24498a2958b358063e6e6d
\ No newline at end of file
+e79c53f02bed0a629c76fd3d044492dc8e619fe9f58c597db5f4417cbe91f805
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-chrome_rendering_desktop_select_slice_with_flows.png.sha256 b/test/data/ui-screenshots/ui-chrome_rendering_desktop_select_slice_with_flows.png.sha256
index 0687a20..0e50d9b 100644
--- a/test/data/ui-screenshots/ui-chrome_rendering_desktop_select_slice_with_flows.png.sha256
+++ b/test/data/ui-screenshots/ui-chrome_rendering_desktop_select_slice_with_flows.png.sha256
@@ -1 +1 @@
-5235f5bfce35b95d2bb39e52faed4e64753e83958bab33b4fd79b1df9f8d89af
\ No newline at end of file
+cc543d6db95f56863f5d6c90dbbb8b07e8dff539534c53d595b1faee807903da
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-modal_dialog_dismiss_1.png.sha256 b/test/data/ui-screenshots/ui-modal_dialog_dismiss_1.png.sha256
index 69e55e1..bf8f89b 100644
--- a/test/data/ui-screenshots/ui-modal_dialog_dismiss_1.png.sha256
+++ b/test/data/ui-screenshots/ui-modal_dialog_dismiss_1.png.sha256
@@ -1 +1 @@
-e7dc92a76eec326637bebaa176482197c621f48bc066fc761d0b1d19513c8c21
\ No newline at end of file
+db689629c3ba9a51e74d48edd3e801bf062dd985ed5210e5a9b4f1bce50f29a7
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-modal_dialog_dismiss_2.png.sha256 b/test/data/ui-screenshots/ui-modal_dialog_dismiss_2.png.sha256
index 67a8dd4..6c30778 100644
--- a/test/data/ui-screenshots/ui-modal_dialog_dismiss_2.png.sha256
+++ b/test/data/ui-screenshots/ui-modal_dialog_dismiss_2.png.sha256
@@ -1 +1 @@
-2d66039e67f93ea58155d19d3be5aba40d3d6f0053f9d1ada63e47828af28abe
\ No newline at end of file
+eae8d6c700a16b5062736c54e4fe0ffab569ffd839715138e74cd257fdb014fa
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-modal_dialog_show_dialog_1.png.sha256 b/test/data/ui-screenshots/ui-modal_dialog_show_dialog_1.png.sha256
index 623260e..5117a65 100644
--- a/test/data/ui-screenshots/ui-modal_dialog_show_dialog_1.png.sha256
+++ b/test/data/ui-screenshots/ui-modal_dialog_show_dialog_1.png.sha256
@@ -1 +1 @@
-b51e0a5035eab217bc4339800e8a6c4025bfc7d5240844c152fbc867b28f75ba
\ No newline at end of file
+5767e81834101bf14dcd1917544f1605b8dbb8aa747a7eefd1c52f4db891575f
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-modal_dialog_show_dialog_2.png.sha256 b/test/data/ui-screenshots/ui-modal_dialog_show_dialog_2.png.sha256
index 679bd39..ff3aafa 100644
--- a/test/data/ui-screenshots/ui-modal_dialog_show_dialog_2.png.sha256
+++ b/test/data/ui-screenshots/ui-modal_dialog_show_dialog_2.png.sha256
@@ -1 +1 @@
-99d3e463fe3812942825829a388bb2d5b11d73010c3213b11d09884dfc1663b5
\ No newline at end of file
+ab1a1b7c948e008fa5d44a4471dc24977f3ab2d592c1ceeaa0ab4afac5bb2336
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-modal_dialog_switch_page_no_dialog.png.sha256 b/test/data/ui-screenshots/ui-modal_dialog_switch_page_no_dialog.png.sha256
index 21fefdd..f4e56d2 100644
--- a/test/data/ui-screenshots/ui-modal_dialog_switch_page_no_dialog.png.sha256
+++ b/test/data/ui-screenshots/ui-modal_dialog_switch_page_no_dialog.png.sha256
@@ -1 +1 @@
-a151d536d2061b45910d894b1735ddc4eac97c4102754d7f1e1b31ebde368675
\ No newline at end of file
+d7c89c766d8db408de06f79654e2f81d8c761c08c4451991447807468df0f3d5
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_navigate_navigate_back_and_forward.png.sha256 b/test/data/ui-screenshots/ui-routing_navigate_navigate_back_and_forward.png.sha256
index 849be2d..46f0129 100644
--- a/test/data/ui-screenshots/ui-routing_navigate_navigate_back_and_forward.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_navigate_navigate_back_and_forward.png.sha256
@@ -1 +1 @@
-4b07a28b92a72568615003beb4eb086adc9be581a27baa2ea593c5e88802647b
\ No newline at end of file
+e596f8037a578f1e58a33bbe08f5d5621b1d37e55456409e5f8799a6897eedb9
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_navigate_open_trace_from_url.png.sha256 b/test/data/ui-screenshots/ui-routing_navigate_open_trace_from_url.png.sha256
index 8e93988..23be44d 100644
--- a/test/data/ui-screenshots/ui-routing_navigate_open_trace_from_url.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_navigate_open_trace_from_url.png.sha256
@@ -1 +1 @@
-56ec21cedc480d6b1b2a894bc70411c89424386a7910d62a09a6a5f1a5921c15
\ No newline at end of file
+b938d4dfcc109165feaedb9421276a355d03a383a0d21ab91ff72409b18a3ab5
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_open_invalid_trace_from_blank_page.png.sha256 b/test/data/ui-screenshots/ui-routing_open_invalid_trace_from_blank_page.png.sha256
index df63f69..b3b1619 100644
--- a/test/data/ui-screenshots/ui-routing_open_invalid_trace_from_blank_page.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_open_invalid_trace_from_blank_page.png.sha256
@@ -1 +1 @@
-10931936be5a35ed461fce47ede47225ffc750a85a13462a614366f26160ca11
\ No newline at end of file
+ae78e1f372a6a052a650974464f2e706ab8cb665c639ca4b0b15b48dce95d185
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_open_trace_and_go_back_to_landing_page.png.sha256 b/test/data/ui-screenshots/ui-routing_open_trace_and_go_back_to_landing_page.png.sha256
index 2afc1a3..0abbaa7 100644
--- a/test/data/ui-screenshots/ui-routing_open_trace_and_go_back_to_landing_page.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_open_trace_and_go_back_to_landing_page.png.sha256
@@ -1 +1 @@
-04e0762424dae233fb13d5cfff51a2d3075ad62220538010d0ab376fc79022a9
\ No newline at end of file
+d62fb2e2f4067552d4f9d4170b4ffa45c74171b4de750292ded957cb6b12b669
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_access_subpage_then_go_back.png.sha256 b/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_access_subpage_then_go_back.png.sha256
index 35c86be..9287876 100644
--- a/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_access_subpage_then_go_back.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_access_subpage_then_go_back.png.sha256
@@ -1 +1 @@
-c8b13c513f261a1749b8699dc868b5152121cc657f0c66eb317df31cab6fdffe
\ No newline at end of file
+30faf223bfc57acbbcca2308c716064d3447dee2673db6329ad9188bf08a59e6
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_open_first_trace_from_url.png.sha256 b/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_open_first_trace_from_url.png.sha256
index 8e93988..23be44d 100644
--- a/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_open_first_trace_from_url.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_open_first_trace_from_url.png.sha256
@@ -1 +1 @@
-56ec21cedc480d6b1b2a894bc70411c89424386a7910d62a09a6a5f1a5921c15
\ No newline at end of file
+b938d4dfcc109165feaedb9421276a355d03a383a0d21ab91ff72409b18a3ab5
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_open_second_trace_from_url.png.sha256 b/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_open_second_trace_from_url.png.sha256
index 35c86be..9287876 100644
--- a/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_open_second_trace_from_url.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_open_two_traces_then_go_back_open_second_trace_from_url.png.sha256
@@ -1 +1 @@
-c8b13c513f261a1749b8699dc868b5152121cc657f0c66eb317df31cab6fdffe
\ No newline at end of file
+30faf223bfc57acbbcca2308c716064d3447dee2673db6329ad9188bf08a59e6
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_start_from_no_trace_go_back_to_first_trace.png.sha256 b/test/data/ui-screenshots/ui-routing_start_from_no_trace_go_back_to_first_trace.png.sha256
index a2e2627..9287876 100644
--- a/test/data/ui-screenshots/ui-routing_start_from_no_trace_go_back_to_first_trace.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_start_from_no_trace_go_back_to_first_trace.png.sha256
@@ -1 +1 @@
-9f0ede90177eeebe804007d5452b0ce62c9739c0caabfef4139efd887851019b
\ No newline at end of file
+30faf223bfc57acbbcca2308c716064d3447dee2673db6329ad9188bf08a59e6
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_start_from_no_trace_go_to_page_with_no_trace.png.sha256 b/test/data/ui-screenshots/ui-routing_start_from_no_trace_go_to_page_with_no_trace.png.sha256
index a494f13..4324721 100644
--- a/test/data/ui-screenshots/ui-routing_start_from_no_trace_go_to_page_with_no_trace.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_start_from_no_trace_go_to_page_with_no_trace.png.sha256
@@ -1 +1 @@
-8de36401497e509ab127d202b83a056c40c2f5f461254f1ea79fe7a4861b059e
\ No newline at end of file
+9d502e8458f85884c7bf1a6411aa3425c63ccf102e6f537318733704e7a416fb
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_invalid_trace.png.sha256 b/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_invalid_trace.png.sha256
index bbc5349..535b9b1 100644
--- a/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_invalid_trace.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_invalid_trace.png.sha256
@@ -1 +1 @@
-d2306dccc59512b2e011a1a40369bcae6f6a8d14131ee66cc346809d938b001d
\ No newline at end of file
+b0d5928fbcf0b7adfc06386ea1961d301ee19f66c61b190f9d00fd5acef824c0
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_second_trace.png.sha256 b/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_second_trace.png.sha256
index 8e93988..23be44d 100644
--- a/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_second_trace.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_second_trace.png.sha256
@@ -1 +1 @@
-56ec21cedc480d6b1b2a894bc70411c89424386a7910d62a09a6a5f1a5921c15
\ No newline at end of file
+b938d4dfcc109165feaedb9421276a355d03a383a0d21ab91ff72409b18a3ab5
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_trace_.png.sha256 b/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_trace_.png.sha256
index 35c86be..9287876 100644
--- a/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_trace_.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_start_from_no_trace_open_trace_.png.sha256
@@ -1 +1 @@
-c8b13c513f261a1749b8699dc868b5152121cc657f0c66eb317df31cab6fdffe
\ No newline at end of file
+30faf223bfc57acbbcca2308c716064d3447dee2673db6329ad9188bf08a59e6
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-routing_start_from_no_trace_refresh.png.sha256 b/test/data/ui-screenshots/ui-routing_start_from_no_trace_refresh.png.sha256
index 35c86be..9287876 100644
--- a/test/data/ui-screenshots/ui-routing_start_from_no_trace_refresh.png.sha256
+++ b/test/data/ui-screenshots/ui-routing_start_from_no_trace_refresh.png.sha256
@@ -1 +1 @@
-c8b13c513f261a1749b8699dc868b5152121cc657f0c66eb317df31cab6fdffe
\ No newline at end of file
+30faf223bfc57acbbcca2308c716064d3447dee2673db6329ad9188bf08a59e6
\ No newline at end of file
diff --git a/test/end_to_end_benchmark.cc b/test/end_to_end_benchmark.cc
index ac7f8fa..ce63780 100644
--- a/test/end_to_end_benchmark.cc
+++ b/test/end_to_end_benchmark.cc
@@ -232,7 +232,7 @@
void ConstantRateProducerArgs(benchmark::internal::Benchmark* b) {
int message_count = IsBenchmarkFunctionalOnly() ? 2 * 1024 : 128 * 1024;
- int min_speed = IsBenchmarkFunctionalOnly() ? 64 : 8;
+ int min_speed = IsBenchmarkFunctionalOnly() ? 128 : 8;
int max_speed = 128;
for (int speed = min_speed; speed <= max_speed; speed *= 2) {
b->Args({message_count, 128, speed});
@@ -242,7 +242,7 @@
void SaturateCpuConsumerArgs(benchmark::internal::Benchmark* b) {
int min_payload = 8;
- int max_payload = IsBenchmarkFunctionalOnly() ? 16 : 64 * 1024;
+ int max_payload = IsBenchmarkFunctionalOnly() ? 8 : 64 * 1024;
for (int bytes = min_payload; bytes <= max_payload; bytes *= 2) {
b->Args({bytes, 0 /* speed */});
}
diff --git a/test/test_helper.cc b/test/test_helper.cc
index cbc3aca..49a9961 100644
--- a/test/test_helper.cc
+++ b/test/test_helper.cc
@@ -290,7 +290,7 @@
void TestHelper::OnObservableEvents(const ObservableEvents&) {}
-void TestHelper::OnSessionCloned(bool, const std::string&) {}
+void TestHelper::OnSessionCloned(const OnSessionClonedArgs&) {}
// static
const char* TestHelper::GetDefaultModeConsumerSocketName() {
diff --git a/test/test_helper.h b/test/test_helper.h
index dd18b4c..2cabd98 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -290,7 +290,7 @@
void OnAttach(bool, const TraceConfig&) override;
void OnTraceStats(bool, const TraceStats&) override;
void OnObservableEvents(const ObservableEvents&) override;
- void OnSessionCloned(bool, const std::string&) override;
+ void OnSessionCloned(const OnSessionClonedArgs&) override;
// Starts the tracing service if in kStartDaemons mode.
void StartServiceIfRequired();
diff --git a/test/trace_processor/diff_tests/android/android_battery_stats_event_slices.out b/test/trace_processor/diff_tests/android/android_battery_stats_event_slices.out
new file mode 100644
index 0000000..82cd36c
--- /dev/null
+++ b/test/trace_processor/diff_tests/android/android_battery_stats_event_slices.out
@@ -0,0 +1,4 @@
+"ts","dur","track_name","str_value","int_value"
+1000,8000,"battery_stats.top","mail",123
+3000,-1,"battery_stats.job","mail_job",456
+1000,3000,"battery_stats.job","video_job",789
diff --git a/test/trace_processor/diff_tests/android/android_battery_stats_state.out b/test/trace_processor/diff_tests/android/android_battery_stats_state.out
new file mode 100644
index 0000000..04ea953
--- /dev/null
+++ b/test/trace_processor/diff_tests/android/android_battery_stats_state.out
@@ -0,0 +1,4 @@
+"ts","track_name","value","value_name","dur"
+1000,"battery_stats.audio",1,"active",-1
+1000,"battery_stats.data_conn",13,"lte",3000
+4000,"battery_stats.data_conn",20,"nr",-1
diff --git a/test/trace_processor/diff_tests/android/android_binder_metric.out b/test/trace_processor/diff_tests/android/android_binder_metric.out
index 8191521..09dc248 100644
--- a/test/trace_processor/diff_tests/android/android_binder_metric.out
+++ b/test/trace_processor/diff_tests/android/android_binder_metric.out
@@ -234,11 +234,13 @@
client_ts: 25827352153
client_dur: 86322
client_tid: 422
+ client_pid: 415
server_process: "system_server"
server_thread: "binder:641_5"
server_ts: 25827417672
server_dur: 11316
server_tid: 1600
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -271,11 +273,13 @@
client_ts: 25827531554
client_dur: 41057
client_tid: 422
+ client_pid: 415
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25827545050
server_dur: 18590
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -308,11 +312,13 @@
client_ts: 25927698833
client_dur: 43619
client_tid: 422
+ client_pid: 415
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25927713489
server_dur: 18478
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -345,11 +351,13 @@
client_ts: 26027844321
client_dur: 76502
client_tid: 422
+ client_pid: 415
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 26027869620
server_dur: 38328
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -382,11 +390,13 @@
client_ts: 26128022950
client_dur: 93620
client_tid: 422
+ client_pid: 415
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 26128060441
server_dur: 42549
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -419,11 +429,13 @@
client_ts: 26228226807
client_dur: 92197
client_tid: 422
+ client_pid: 415
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 26228257962
server_dur: 47691
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -456,11 +468,13 @@
client_ts: 26328427074
client_dur: 88516
client_tid: 422
+ client_pid: 415
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 26328457296
server_dur: 45253
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -493,11 +507,13 @@
client_ts: 21625430256
client_dur: 106084
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21625451288
server_dur: 25329
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -530,11 +546,13 @@
client_ts: 21651104412
client_dur: 1553854
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21651127883
server_dur: 24255
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -567,11 +585,13 @@
client_ts: 21681078075
client_dur: 6957581
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21681097331
server_dur: 20398
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -604,11 +624,13 @@
client_ts: 21713184564
client_dur: 1238385
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21713209886
server_dur: 8733
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -641,11 +663,13 @@
client_ts: 21745330426
client_dur: 2415345
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21745354167
server_dur: 24535
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -678,11 +702,13 @@
client_ts: 21772841582
client_dur: 60073
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21772864934
server_dur: 21372
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -715,11 +741,13 @@
client_ts: 21797991492
client_dur: 58946
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21798015547
server_dur: 20885
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -752,11 +780,13 @@
client_ts: 21823141587
client_dur: 61370
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21823167028
server_dur: 21656
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -789,11 +819,13 @@
client_ts: 21848290804
client_dur: 60709
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21848316259
server_dur: 20391
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -826,11 +858,13 @@
client_ts: 21873440775
client_dur: 55934
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21873461764
server_dur: 21136
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -863,11 +897,13 @@
client_ts: 21898589558
client_dur: 58875
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21898611789
server_dur: 20494
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -900,11 +936,13 @@
client_ts: 21923738957
client_dur: 64169
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21923761253
server_dur: 25784
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -937,11 +975,13 @@
client_ts: 21948891420
client_dur: 64699
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21948920277
server_dur: 20540
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -974,11 +1014,13 @@
client_ts: 21974296208
client_dur: 104989
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21974341636
server_dur: 25187
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1011,11 +1053,13 @@
client_ts: 21999539011
client_dur: 71202
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21999568501
server_dur: 20357
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1048,11 +1092,13 @@
client_ts: 22024711257
client_dur: 328183
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22024736108
server_dur: 25338
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1085,11 +1131,13 @@
client_ts: 22050132357
client_dur: 59459
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22050156562
server_dur: 20679
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1122,11 +1170,13 @@
client_ts: 22075288214
client_dur: 58461
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22075311405
server_dur: 20809
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1159,11 +1209,13 @@
client_ts: 22100443015
client_dur: 66715
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22100466870
server_dur: 19761
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1196,11 +1248,13 @@
client_ts: 22125600618
client_dur: 65545
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22125623322
server_dur: 20702
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1233,11 +1287,13 @@
client_ts: 22150759363
client_dur: 56369
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22150779993
server_dur: 22255
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1270,11 +1326,13 @@
client_ts: 22175906178
client_dur: 63847
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22175929226
server_dur: 25370
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1307,11 +1365,13 @@
client_ts: 22201561660
client_dur: 209987
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22201735902
server_dur: 20781
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1344,11 +1404,13 @@
client_ts: 22227603566
client_dur: 61556
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22227627247
server_dur: 19354
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1381,11 +1443,13 @@
client_ts: 22252767831
client_dur: 65418
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22252793033
server_dur: 24322
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1418,11 +1482,13 @@
client_ts: 22277925922
client_dur: 297059
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22278187629
server_dur: 20875
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1455,11 +1521,13 @@
client_ts: 22303375651
client_dur: 55580
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22303396802
server_dur: 20656
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1492,11 +1560,13 @@
client_ts: 22328804156
client_dur: 83145
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22328852158
server_dur: 21212
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1529,11 +1599,13 @@
client_ts: 22354003523
client_dur: 56819
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22354025291
server_dur: 20568
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1566,11 +1638,13 @@
client_ts: 22379156345
client_dur: 66779
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22379180900
server_dur: 25632
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1603,11 +1677,13 @@
client_ts: 22404448968
client_dur: 67438
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22404473541
server_dur: 24816
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1640,11 +1716,13 @@
client_ts: 22429616334
client_dur: 74108
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22429639907
server_dur: 32292
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1677,11 +1755,13 @@
client_ts: 22455238568
client_dur: 55788
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22455259634
server_dur: 20555
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1714,11 +1794,13 @@
client_ts: 22480383875
client_dur: 56554
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22480404678
server_dur: 20572
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1751,11 +1833,13 @@
client_ts: 22505531489
client_dur: 59218
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22505553139
server_dur: 22859
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1788,11 +1872,13 @@
client_ts: 22531090402
client_dur: 56749
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22531111630
server_dur: 20210
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1825,11 +1911,13 @@
client_ts: 22556242635
client_dur: 57252
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22556262293
server_dur: 20917
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1862,11 +1950,13 @@
client_ts: 22581426858
client_dur: 266380
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22581641694
server_dur: 31182
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1905,11 +1995,13 @@
client_ts: 22606961662
client_dur: 557886
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22606985795
server_dur: 21756
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1942,11 +2034,13 @@
client_ts: 22632616662
client_dur: 57814
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22632638644
server_dur: 20728
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -1979,11 +2073,13 @@
client_ts: 22657890096
client_dur: 63825
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22657912861
server_dur: 22058
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2016,11 +2112,13 @@
client_ts: 22683093531
client_dur: 80792
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22683116244
server_dur: 21278
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2059,11 +2157,13 @@
client_ts: 22708307977
client_dur: 67445
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22708332522
server_dur: 26370
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2096,11 +2196,13 @@
client_ts: 22733506276
client_dur: 119221
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22733593661
server_dur: 19257
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2133,11 +2235,13 @@
client_ts: 22758727072
client_dur: 446508
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22759138073
server_dur: 20676
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2170,11 +2274,13 @@
client_ts: 22784311059
client_dur: 161051
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22784409798
server_dur: 20874
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2207,11 +2313,13 @@
client_ts: 22809748047
client_dur: 57852
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22809770020
server_dur: 20538
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2244,11 +2352,13 @@
client_ts: 22834902012
client_dur: 93361
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22834959559
server_dur: 21369
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2281,11 +2391,13 @@
client_ts: 22860898758
client_dur: 82717
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22860942436
server_dur: 21910
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2318,11 +2430,13 @@
client_ts: 22886110503
client_dur: 99316
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22886176653
server_dur: 20849
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2355,11 +2469,13 @@
client_ts: 22911318220
client_dur: 66992
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22911345648
server_dur: 22362
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2392,11 +2508,13 @@
client_ts: 22936549304
client_dur: 58969
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22936570719
server_dur: 21297
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2429,11 +2547,13 @@
client_ts: 22961701152
client_dur: 676548
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22962339912
server_dur: 22166
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2466,11 +2586,13 @@
client_ts: 22987512708
client_dur: 79649
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22987551432
server_dur: 24288
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2509,11 +2631,13 @@
client_ts: 23013143578
client_dur: 61635
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23013168634
server_dur: 20531
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2546,11 +2670,13 @@
client_ts: 23038642421
client_dur: 137175
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23038736570
server_dur: 20651
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2583,11 +2709,13 @@
client_ts: 23063886880
client_dur: 55663
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23063908358
server_dur: 16544
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2620,11 +2748,13 @@
client_ts: 23089198686
client_dur: 68926
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23089221371
server_dur: 23561
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2663,11 +2793,13 @@
client_ts: 23114443451
client_dur: 64468
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23114469373
server_dur: 23341
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2700,11 +2832,13 @@
client_ts: 23139601722
client_dur: 78228
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23139640251
server_dur: 21320
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2737,11 +2871,13 @@
client_ts: 23164771069
client_dur: 91260
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23164821900
server_dur: 21423
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2774,11 +2910,13 @@
client_ts: 23189996807
client_dur: 214050
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23190162200
server_dur: 20825
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2817,11 +2955,13 @@
client_ts: 23215317200
client_dur: 57982
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23215338281
server_dur: 21069
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2854,11 +2994,13 @@
client_ts: 23240472994
client_dur: 61104
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23240494382
server_dur: 22737
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2891,11 +3033,13 @@
client_ts: 23265633084
client_dur: 257686
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23265855074
server_dur: 21119
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2928,11 +3072,13 @@
client_ts: 23294001031
client_dur: 68360
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23294024310
server_dur: 25000
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -2965,11 +3111,13 @@
client_ts: 23319166709
client_dur: 255922
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23319381423
server_dur: 24946
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3002,11 +3150,13 @@
client_ts: 23344525034
client_dur: 66275
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23344548135
server_dur: 25737
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3039,11 +3189,13 @@
client_ts: 23369688943
client_dur: 61329
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23369711803
server_dur: 22061
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3076,11 +3228,13 @@
client_ts: 23394850079
client_dur: 540888
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23395351729
server_dur: 22192
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3113,11 +3267,13 @@
client_ts: 23420492464
client_dur: 65743
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23420518127
server_dur: 22480
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3150,11 +3306,13 @@
client_ts: 23451713078
client_dur: 68421
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23451738606
server_dur: 24478
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3187,11 +3345,13 @@
client_ts: 23476881893
client_dur: 64782
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23476905553
server_dur: 24602
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3224,11 +3384,13 @@
client_ts: 23502042821
client_dur: 820095
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23502825079
server_dur: 23414
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3261,11 +3423,13 @@
client_ts: 23527974198
client_dur: 845116
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23528782089
server_dur: 23126
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3298,11 +3462,13 @@
client_ts: 23553917567
client_dur: 59738
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23553940355
server_dur: 21362
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3335,11 +3501,13 @@
client_ts: 23579071838
client_dur: 411519
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23579443790
server_dur: 25365
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3372,11 +3540,13 @@
client_ts: 23604582593
client_dur: 210023
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23604751577
server_dur: 24165
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3409,11 +3579,13 @@
client_ts: 23629892322
client_dur: 194538
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23630049856
server_dur: 21631
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3446,11 +3618,13 @@
client_ts: 23655179880
client_dur: 142025
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23655273690
server_dur: 30591
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3483,11 +3657,13 @@
client_ts: 23680421874
client_dur: 72852
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23680450743
server_dur: 26736
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3520,11 +3696,13 @@
client_ts: 23705597440
client_dur: 470856
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23706033599
server_dur: 21348
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3557,11 +3735,13 @@
client_ts: 23731172177
client_dur: 184006
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23731318438
server_dur: 21088
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3594,11 +3774,13 @@
client_ts: 23757576836
client_dur: 69175
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23757598859
server_dur: 22748
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3631,11 +3813,13 @@
client_ts: 23782737996
client_dur: 59451
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23782758417
server_dur: 25123
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3668,11 +3852,13 @@
client_ts: 23807891211
client_dur: 62509
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23807914516
server_dur: 23582
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3705,11 +3891,13 @@
client_ts: 23833055418
client_dur: 163286
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23833182220
server_dur: 22315
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3742,11 +3930,13 @@
client_ts: 23858313038
client_dur: 57714
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23858335729
server_dur: 20454
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3779,11 +3969,13 @@
client_ts: 23883462809
client_dur: 59212
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23883487934
server_dur: 19666
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3816,11 +4008,13 @@
client_ts: 23908617410
client_dur: 67454
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23908643220
server_dur: 25095
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3853,11 +4047,13 @@
client_ts: 23933826058
client_dur: 54993
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23933846583
server_dur: 19834
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3890,11 +4086,13 @@
client_ts: 23958974344
client_dur: 56757
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23958997349
server_dur: 19668
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3927,11 +4125,13 @@
client_ts: 23984212731
client_dur: 65425
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23984244337
server_dur: 18760
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -3964,11 +4164,13 @@
client_ts: 24009326493
client_dur: 55937
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24009348026
server_dur: 20878
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4001,11 +4203,13 @@
client_ts: 24034474905
client_dur: 323973
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24034762131
server_dur: 21724
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4038,11 +4242,13 @@
client_ts: 24059888481
client_dur: 269355
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24060121507
server_dur: 21099
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4075,11 +4281,13 @@
client_ts: 24085507070
client_dur: 65864
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24085532155
server_dur: 24607
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4112,11 +4320,13 @@
client_ts: 24110668836
client_dur: 62135
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24110692176
server_dur: 23546
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4149,11 +4359,13 @@
client_ts: 24135822325
client_dur: 55790
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24135843301
server_dur: 20745
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4186,11 +4398,13 @@
client_ts: 24160973601
client_dur: 64296
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24160998105
server_dur: 24373
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4223,11 +4437,13 @@
client_ts: 24186129350
client_dur: 61214
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24186153807
server_dur: 21100
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4260,11 +4476,13 @@
client_ts: 24211335205
client_dur: 99239
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24211379278
server_dur: 25032
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4297,11 +4515,13 @@
client_ts: 24236559912
client_dur: 85757
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24236597491
server_dur: 27319
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4334,11 +4554,13 @@
client_ts: 24261743662
client_dur: 72120
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24261771646
server_dur: 25209
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4371,11 +4593,13 @@
client_ts: 24286913419
client_dur: 330217
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24287198196
server_dur: 22848
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4408,11 +4632,13 @@
client_ts: 24312358034
client_dur: 69020
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24312388724
server_dur: 21476
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4451,11 +4677,13 @@
client_ts: 24337574519
client_dur: 104255
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24337613079
server_dur: 33967
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4488,11 +4716,13 @@
client_ts: 24362804629
client_dur: 58822
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24362826557
server_dur: 20783
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4525,11 +4755,13 @@
client_ts: 24387968494
client_dur: 63171
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24387991414
server_dur: 24460
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4562,11 +4794,13 @@
client_ts: 24414399633
client_dur: 3357310
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24414422286
server_dur: 20459
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4599,11 +4833,13 @@
client_ts: 24443111092
client_dur: 63218
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24443132289
server_dur: 23717
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4636,11 +4872,13 @@
client_ts: 24468268772
client_dur: 63940
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24468295057
server_dur: 21634
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4673,11 +4911,13 @@
client_ts: 24493507908
client_dur: 75072
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24493536500
server_dur: 22590
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4710,11 +4950,13 @@
client_ts: 24518715570
client_dur: 83147
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24518746589
server_dur: 20133
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4747,11 +4989,13 @@
client_ts: 24544028919
client_dur: 105487
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24544069334
server_dur: 24026
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4784,11 +5028,13 @@
client_ts: 24569328112
client_dur: 106610
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24569369501
server_dur: 41826
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4821,11 +5067,13 @@
client_ts: 24594543032
client_dur: 45871
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24594558488
server_dur: 20382
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4852,11 +5100,13 @@
client_ts: 24619690623
client_dur: 58336
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24619710131
server_dur: 25779
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4883,11 +5133,13 @@
client_ts: 24644930551
client_dur: 105892
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24644975052
server_dur: 34388
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4920,11 +5172,13 @@
client_ts: 24670207638
client_dur: 54225
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24670224041
server_dur: 26208
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4951,11 +5205,13 @@
client_ts: 24695363832
client_dur: 47347
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24695380382
server_dur: 19885
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -4982,11 +5238,13 @@
client_ts: 24720504163
client_dur: 41635
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24720517121
server_dur: 18951
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5013,11 +5271,13 @@
client_ts: 24745651155
client_dur: 50201
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24745667169
server_dur: 21953
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5044,11 +5304,13 @@
client_ts: 24770795510
client_dur: 45248
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24770810644
server_dur: 19730
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5075,11 +5337,13 @@
client_ts: 24795949562
client_dur: 44458
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24795964339
server_dur: 19474
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5106,11 +5370,13 @@
client_ts: 24821098319
client_dur: 45736
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24821113887
server_dur: 19916
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5137,11 +5403,13 @@
client_ts: 24846533416
client_dur: 52565
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24846550147
server_dur: 20978
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5168,11 +5436,13 @@
client_ts: 24871959612
client_dur: 33762
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24871969021
server_dur: 15109
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5199,11 +5469,13 @@
client_ts: 24897089502
client_dur: 36235
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24897101194
server_dur: 15306
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5230,11 +5502,13 @@
client_ts: 24922327702
client_dur: 47487
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24922343062
server_dur: 20895
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5261,11 +5535,13 @@
client_ts: 24947478390
client_dur: 50011
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24947495490
server_dur: 21244
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5292,11 +5568,13 @@
client_ts: 24972625739
client_dur: 46864
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24972642054
server_dur: 20460
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5323,11 +5601,13 @@
client_ts: 24997766928
client_dur: 105830
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24997800832
server_dur: 45031
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5360,11 +5640,13 @@
client_ts: 25023405381
client_dur: 86423
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25023438732
server_dur: 29757
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5397,11 +5679,13 @@
client_ts: 25048609139
client_dur: 56222
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25048631235
server_dur: 16655
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5434,11 +5718,13 @@
client_ts: 25073875780
client_dur: 84120
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25073898205
server_dur: 15854
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5471,11 +5757,13 @@
client_ts: 25099064916
client_dur: 204188
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25099198462
server_dur: 49025
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5508,11 +5796,13 @@
client_ts: 25124642124
client_dur: 68889
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25124666670
server_dur: 29243
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5539,11 +5829,13 @@
client_ts: 25149891522
client_dur: 60500
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25149912505
server_dur: 27000
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5570,11 +5862,13 @@
client_ts: 25175121734
client_dur: 65293
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25175141892
server_dur: 23570
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5607,11 +5901,13 @@
client_ts: 25200283959
client_dur: 44045
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25200298152
server_dur: 19339
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5638,11 +5934,13 @@
client_ts: 25225419452
client_dur: 43144
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25225434070
server_dur: 18615
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5669,11 +5967,13 @@
client_ts: 25250561510
client_dur: 82814
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25250589325
server_dur: 36944
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5706,11 +6006,13 @@
client_ts: 25275837002
client_dur: 111602
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25275893327
server_dur: 33040
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5743,11 +6045,13 @@
client_ts: 25301779154
client_dur: 81058
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25301805031
server_dur: 24119
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5780,11 +6084,13 @@
client_ts: 25327028096
client_dur: 144639
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25327077936
server_dur: 53753
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5817,11 +6123,13 @@
client_ts: 25352301178
client_dur: 837973
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25353047151
server_dur: 48734
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5854,11 +6162,13 @@
client_ts: 25378250275
client_dur: 77754
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25378276198
server_dur: 28616
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5891,11 +6201,13 @@
client_ts: 25403423456
client_dur: 65101
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25403445450
server_dur: 23191
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -5929,11 +6241,13 @@
client_ts: 25403532822
client_dur: 243238
client_tid: 492
+ client_pid: 492
server_process: "system_server"
server_thread: "binder:641_4"
server_ts: 25403547799
server_dur: 210707
server_tid: 1596
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -5972,11 +6286,13 @@
client_ts: 25403800150
client_dur: 77678
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25403821750
server_dur: 43829
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6009,11 +6325,13 @@
client_ts: 25429003446
client_dur: 55342
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25429021995
server_dur: 20582
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6046,11 +6364,13 @@
client_ts: 25454157095
client_dur: 68221
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25454182918
server_dur: 20352
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6083,11 +6403,13 @@
client_ts: 25479325945
client_dur: 157863
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25479422370
server_dur: 35765
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6120,11 +6442,13 @@
client_ts: 25504631134
client_dur: 1082750
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25505253998
server_dur: 109396
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6158,11 +6482,13 @@
client_ts: 25505818197
client_dur: 3125407
client_tid: 492
+ client_pid: 492
server_process: "system_server"
server_thread: "binder:641_4"
server_ts: 25505891588
server_dur: 3000749
server_tid: 1596
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -6220,11 +6546,13 @@
client_ts: 25508998675
client_dur: 379026
client_tid: 492
+ client_pid: 492
server_process: "system_server"
server_thread: "binder:641_4"
server_ts: 25509052778
server_dur: 272193
server_tid: 1596
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6257,11 +6585,13 @@
client_ts: 25512878756
client_dur: 151351
client_tid: 492
+ client_pid: 492
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25512939518
server_dur: 62943
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6294,11 +6624,13 @@
client_ts: 21612276580
client_dur: 39977
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21612292301
server_dur: 14064
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6331,11 +6663,13 @@
client_ts: 21637405403
client_dur: 60035
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21637427285
server_dur: 24550
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6368,11 +6702,13 @@
client_ts: 21662560974
client_dur: 372941
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21662897046
server_dur: 22907
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6405,11 +6741,13 @@
client_ts: 21688024281
client_dur: 59297
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21688047484
server_dur: 21173
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6442,11 +6780,13 @@
client_ts: 21713127573
client_dur: 63596
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21713152373
server_dur: 21155
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6479,11 +6819,13 @@
client_ts: 21738283156
client_dur: 60407
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21738305184
server_dur: 24886
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6516,11 +6858,13 @@
client_ts: 21763445363
client_dur: 70801
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21763467940
server_dur: 30748
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6553,11 +6897,13 @@
client_ts: 21788612931
client_dur: 57076
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21788635008
server_dur: 21359
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6590,11 +6936,13 @@
client_ts: 21813762065
client_dur: 61236
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21813783295
server_dur: 25042
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6627,11 +6975,13 @@
client_ts: 21838919344
client_dur: 59886
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21838943470
server_dur: 20686
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6664,11 +7014,13 @@
client_ts: 21864144722
client_dur: 71604
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21864171886
server_dur: 25966
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6701,11 +7053,13 @@
client_ts: 21889317261
client_dur: 517889
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21889524828
server_dur: 21638
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6738,11 +7092,13 @@
client_ts: 21914927560
client_dur: 59832
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21914949348
server_dur: 23104
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6775,11 +7131,13 @@
client_ts: 21940080190
client_dur: 63873
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21940103851
server_dur: 24784
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6812,11 +7170,13 @@
client_ts: 21965236304
client_dur: 87480
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21965262841
server_dur: 47604
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -6855,11 +7215,13 @@
client_ts: 21990454958
client_dur: 89222
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21990491103
server_dur: 25934
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6892,11 +7254,13 @@
client_ts: 22015656850
client_dur: 62246
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22015682089
server_dur: 21161
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6929,11 +7293,13 @@
client_ts: 22040814163
client_dur: 64221
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22040838835
server_dur: 24377
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -6966,11 +7332,13 @@
client_ts: 22066737714
client_dur: 128820
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22066831151
server_dur: 19563
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7003,11 +7371,13 @@
client_ts: 22091960087
client_dur: 58325
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22091982875
server_dur: 21344
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7040,11 +7410,13 @@
client_ts: 22117113923
client_dur: 63410
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22117137718
server_dur: 23868
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7077,11 +7449,13 @@
client_ts: 22142267357
client_dur: 59986
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22142291376
server_dur: 21134
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7114,11 +7488,13 @@
client_ts: 22167423522
client_dur: 59967
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22167445520
server_dur: 22511
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7151,11 +7527,13 @@
client_ts: 22192579344
client_dur: 60820
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22192603786
server_dur: 21006
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7188,11 +7566,13 @@
client_ts: 22217730341
client_dur: 55283
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22217750903
server_dur: 20680
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7225,11 +7605,13 @@
client_ts: 22242880300
client_dur: 71100
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22242905309
server_dur: 26682
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7262,11 +7644,13 @@
client_ts: 22268043393
client_dur: 409558
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22268414904
server_dur: 21405
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7299,11 +7683,13 @@
client_ts: 22293548146
client_dur: 63871
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22293572042
server_dur: 22980
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7336,11 +7722,13 @@
client_ts: 22318716098
client_dur: 339826
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22318736854
server_dur: 23010
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7373,11 +7761,13 @@
client_ts: 22344146679
client_dur: 110188
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22344218394
server_dur: 24011
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7410,11 +7800,13 @@
client_ts: 22369334226
client_dur: 94388
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22369355609
server_dur: 48856
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7447,11 +7839,13 @@
client_ts: 22394536230
client_dur: 62982
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22394561551
server_dur: 22059
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7484,11 +7878,13 @@
client_ts: 22419697576
client_dur: 61323
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22419722756
server_dur: 21994
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7521,11 +7917,13 @@
client_ts: 22445031509
client_dur: 50515
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22445050820
server_dur: 17128
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7558,11 +7956,13 @@
client_ts: 22470174653
client_dur: 55822
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22470196239
server_dur: 21286
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7595,11 +7995,13 @@
client_ts: 22495325972
client_dur: 68180
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22495350975
server_dur: 26711
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7632,11 +8034,13 @@
client_ts: 22521360985
client_dur: 234231
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22521382730
server_dur: 21186
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7669,11 +8073,13 @@
client_ts: 22546697891
client_dur: 98444
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22546761058
server_dur: 19881
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7706,11 +8112,13 @@
client_ts: 22571892907
client_dur: 66101
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22571916881
server_dur: 25795
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7743,11 +8151,13 @@
client_ts: 22597062070
client_dur: 259462
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22597272531
server_dur: 34173
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7780,11 +8190,13 @@
client_ts: 22622418577
client_dur: 59816
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22622443274
server_dur: 21430
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7817,11 +8229,13 @@
client_ts: 22650180912
client_dur: 473997
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22650255041
server_dur: 19254
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7854,11 +8268,13 @@
client_ts: 22675764005
client_dur: 70615
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22675789713
server_dur: 25069
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7891,11 +8307,13 @@
client_ts: 22701432879
client_dur: 450491
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22701762194
server_dur: 23978
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7928,11 +8346,13 @@
client_ts: 22726978606
client_dur: 401005
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22727339544
server_dur: 23475
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -7965,11 +8385,13 @@
client_ts: 22752478293
client_dur: 586574
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22753025360
server_dur: 21422
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8002,11 +8424,13 @@
client_ts: 22778161650
client_dur: 349397
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22778472830
server_dur: 22980
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8039,11 +8463,13 @@
client_ts: 22803612048
client_dur: 67634
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22803636072
server_dur: 23917
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8076,11 +8502,13 @@
client_ts: 22828777874
client_dur: 318230
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22828822556
server_dur: 26877
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8113,11 +8541,13 @@
client_ts: 22854196228
client_dur: 561632
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22854720488
server_dur: 21460
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8150,11 +8580,13 @@
client_ts: 22879856680
client_dur: 63364
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22879882339
server_dur: 22238
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8187,11 +8619,13 @@
client_ts: 22905018627
client_dur: 66122
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22905041577
server_dur: 26326
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8224,11 +8658,13 @@
client_ts: 22930183511
client_dur: 67161
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22930213119
server_dur: 23605
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8261,11 +8697,13 @@
client_ts: 22955349414
client_dur: 156341
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22955463649
server_dur: 24599
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8298,11 +8736,13 @@
client_ts: 22980607439
client_dur: 65794
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22980629549
server_dur: 26192
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8335,11 +8775,13 @@
client_ts: 23005774838
client_dur: 62936
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23005798704
server_dur: 23801
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8372,11 +8814,13 @@
client_ts: 23030941978
client_dur: 89285
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23030973182
server_dur: 37855
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8409,11 +8853,13 @@
client_ts: 23056174448
client_dur: 200618
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23056329883
server_dur: 23980
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8446,11 +8892,13 @@
client_ts: 23081467052
client_dur: 59125
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23081486828
server_dur: 24680
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8483,11 +8931,13 @@
client_ts: 23106620846
client_dur: 61616
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23106642188
server_dur: 24012
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8520,11 +8970,13 @@
client_ts: 23131777328
client_dur: 123447
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23131861232
server_dur: 22637
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8557,11 +9009,13 @@
client_ts: 23157002672
client_dur: 79156
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23157030248
server_dur: 27226
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8594,11 +9048,13 @@
client_ts: 23182173903
client_dur: 376646
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23182500065
server_dur: 21132
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8631,11 +9087,13 @@
client_ts: 23207650439
client_dur: 67278
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23207680535
server_dur: 23155
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8668,11 +9126,13 @@
client_ts: 23233851428
client_dur: 892848
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23233871293
server_dur: 23312
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8705,11 +9165,13 @@
client_ts: 23259841421
client_dur: 63174
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23259863994
server_dur: 23889
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8742,11 +9204,13 @@
client_ts: 23284999517
client_dur: 56437
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23285019554
server_dur: 21307
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8779,11 +9243,13 @@
client_ts: 23310151865
client_dur: 642229
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23310751409
server_dur: 26103
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8816,11 +9282,13 @@
client_ts: 23335905400
client_dur: 357982
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23336222503
server_dur: 25821
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8853,11 +9321,13 @@
client_ts: 23361328882
client_dur: 63784
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23361351852
server_dur: 24700
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8890,11 +9360,13 @@
client_ts: 23386869959
client_dur: 66376
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23386894766
server_dur: 25613
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8927,11 +9399,13 @@
client_ts: 23412468379
client_dur: 144242
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23412492591
server_dur: 28309
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -8964,11 +9438,13 @@
client_ts: 23437712307
client_dur: 61646
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23437733692
server_dur: 21877
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9001,11 +9477,13 @@
client_ts: 23462870779
client_dur: 64694
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23462898239
server_dur: 21829
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9038,11 +9516,13 @@
client_ts: 23488042638
client_dur: 69970
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23488068942
server_dur: 26303
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9075,11 +9555,13 @@
client_ts: 23513211192
client_dur: 57998
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23513232838
server_dur: 22355
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9112,11 +9594,13 @@
client_ts: 23538364057
client_dur: 90805
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23538417034
server_dur: 21543
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9149,11 +9633,13 @@
client_ts: 23563555747
client_dur: 62301
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23563577896
server_dur: 23477
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9186,11 +9672,13 @@
client_ts: 23588716088
client_dur: 122069
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23588796199
server_dur: 21803
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9223,11 +9711,13 @@
client_ts: 23613942195
client_dur: 406560
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23614311041
server_dur: 21665
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9260,11 +9750,13 @@
client_ts: 23639449764
client_dur: 297834
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23639707345
server_dur: 24585
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9297,11 +9789,13 @@
client_ts: 23664840926
client_dur: 64026
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23664863549
server_dur: 25828
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9334,11 +9828,13 @@
client_ts: 23689999571
client_dur: 60667
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23690020989
server_dur: 24039
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9371,11 +9867,13 @@
client_ts: 23715668567
client_dur: 55651
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23715687865
server_dur: 20534
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9408,11 +9906,13 @@
client_ts: 23740820398
client_dur: 69779
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23740846289
server_dur: 26005
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9445,11 +9945,13 @@
client_ts: 23765983216
client_dur: 63111
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23766008333
server_dur: 22489
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9482,11 +9984,13 @@
client_ts: 23791142714
client_dur: 62184
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23791165515
server_dur: 24176
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9519,11 +10023,13 @@
client_ts: 23816748979
client_dur: 97527
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23816810994
server_dur: 19216
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9556,11 +10062,13 @@
client_ts: 23841937008
client_dur: 265351
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23842045870
server_dur: 21030
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9593,11 +10101,13 @@
client_ts: 23867298197
client_dur: 65269
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23867323342
server_dur: 24762
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9630,11 +10140,13 @@
client_ts: 23892458661
client_dur: 61895
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23892481485
server_dur: 23511
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9667,11 +10179,13 @@
client_ts: 23917612205
client_dur: 60756
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23917632161
server_dur: 27790
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9704,11 +10218,13 @@
client_ts: 23942767445
client_dur: 56639
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23942789248
server_dur: 20150
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9741,11 +10257,13 @@
client_ts: 23967917345
client_dur: 61714
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23967941212
server_dur: 23677
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9778,11 +10296,13 @@
client_ts: 23993073217
client_dur: 61426
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23993098746
server_dur: 21011
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9815,11 +10335,13 @@
client_ts: 24018227157
client_dur: 154788
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24018346321
server_dur: 21354
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9852,11 +10374,13 @@
client_ts: 24043472861
client_dur: 56072
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24043492721
server_dur: 20952
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9889,11 +10413,13 @@
client_ts: 24068623147
client_dur: 61422
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24068647003
server_dur: 23307
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9926,11 +10452,13 @@
client_ts: 24094174551
client_dur: 60440
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24094198265
server_dur: 20963
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -9963,11 +10491,13 @@
client_ts: 24119330336
client_dur: 62796
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24119353765
server_dur: 24014
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10000,11 +10530,13 @@
client_ts: 24144486541
client_dur: 57521
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24144507336
server_dur: 20651
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10037,11 +10569,13 @@
client_ts: 24169644272
client_dur: 59318
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24169667507
server_dur: 21848
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10074,11 +10608,13 @@
client_ts: 24194796993
client_dur: 61133
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24194818919
server_dur: 24981
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10111,11 +10647,13 @@
client_ts: 24219976971
client_dur: 80874
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24220009018
server_dur: 24029
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10148,11 +10686,13 @@
client_ts: 24245182141
client_dur: 75715
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24245212188
server_dur: 24869
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10185,11 +10725,13 @@
client_ts: 24270354623
client_dur: 72978
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24270381508
server_dur: 24460
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10222,11 +10764,13 @@
client_ts: 24296497808
client_dur: 74119
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24296524147
server_dur: 25619
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10259,11 +10803,13 @@
client_ts: 24321677437
client_dur: 1068351
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24322701227
server_dur: 22458
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10296,11 +10842,13 @@
client_ts: 24349464998
client_dur: 600120
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24349498235
server_dur: 21721
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10333,11 +10881,13 @@
client_ts: 24375203138
client_dur: 200814
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24375371665
server_dur: 20774
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10370,11 +10920,13 @@
client_ts: 24400499298
client_dur: 1655381
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24400525814
server_dur: 20740
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10407,11 +10959,13 @@
client_ts: 24427255856
client_dur: 74073
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24427281368
server_dur: 33400
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10444,11 +10998,13 @@
client_ts: 24452425092
client_dur: 66019
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24452453488
server_dur: 22713
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10481,11 +11037,13 @@
client_ts: 24477584081
client_dur: 77570
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24477603311
server_dur: 20359
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10518,11 +11076,13 @@
client_ts: 24502766882
client_dur: 85030
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24502792394
server_dur: 34540
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10555,11 +11115,13 @@
client_ts: 24528063792
client_dur: 88744
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24528100762
server_dur: 19035
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10592,11 +11154,13 @@
client_ts: 24553269933
client_dur: 102641
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24553320732
server_dur: 19753
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10629,11 +11193,13 @@
client_ts: 24578496582
client_dur: 75733
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24578522139
server_dur: 31879
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10666,11 +11232,13 @@
client_ts: 24603666160
client_dur: 32902
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24603676548
server_dur: 13734
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10703,11 +11271,13 @@
client_ts: 24628827055
client_dur: 77433
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24628855199
server_dur: 31376
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10740,11 +11310,13 @@
client_ts: 24654016554
client_dur: 82862
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24654047419
server_dur: 27392
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10777,11 +11349,13 @@
client_ts: 24679300128
client_dur: 51067
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24679317330
server_dur: 23251
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10814,11 +11388,13 @@
client_ts: 24704445330
client_dur: 53313
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24704463794
server_dur: 20543
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10851,11 +11427,13 @@
client_ts: 24729604221
client_dur: 73960
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24729643378
server_dur: 19819
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10888,11 +11466,13 @@
client_ts: 24754787089
client_dur: 79191
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24754812563
server_dur: 21216
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10925,11 +11505,13 @@
client_ts: 24779973546
client_dur: 61655
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24779997866
server_dur: 21840
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10962,11 +11544,13 @@
client_ts: 24805151631
client_dur: 65179
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24805176625
server_dur: 24502
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -10999,11 +11583,13 @@
client_ts: 24830317956
client_dur: 66289
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24830344368
server_dur: 21990
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11036,11 +11622,13 @@
client_ts: 24855481377
client_dur: 65228
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24855502595
server_dur: 27360
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11073,11 +11661,13 @@
client_ts: 24880648226
client_dur: 55511
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24880667129
server_dur: 21590
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11110,11 +11700,13 @@
client_ts: 24909335836
client_dur: 55761
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24909354477
server_dur: 24104
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11147,11 +11739,13 @@
client_ts: 24934490094
client_dur: 58244
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24934509872
server_dur: 22084
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11184,11 +11778,13 @@
client_ts: 24959652634
client_dur: 81523
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24959684793
server_dur: 28526
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11221,11 +11817,13 @@
client_ts: 24984851591
client_dur: 68470
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24984877747
server_dur: 26966
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11258,11 +11856,13 @@
client_ts: 25010040890
client_dur: 90947
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25010071568
server_dur: 37280
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11295,11 +11895,13 @@
client_ts: 25035275877
client_dur: 59761
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25035296221
server_dur: 25210
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11332,11 +11934,13 @@
client_ts: 25060426543
client_dur: 81204
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25060443769
server_dur: 22941
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11369,11 +11973,13 @@
client_ts: 25085672790
client_dur: 95011
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25085716849
server_dur: 37413
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11406,11 +12012,13 @@
client_ts: 25110861456
client_dur: 53363
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25110879022
server_dur: 22707
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11443,11 +12051,13 @@
client_ts: 25136012642
client_dur: 51978
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25136030960
server_dur: 22166
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11480,11 +12090,13 @@
client_ts: 25161156360
client_dur: 68046
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25161174689
server_dur: 37221
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11517,11 +12129,13 @@
client_ts: 25186325904
client_dur: 37128
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25186338341
server_dur: 14526
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11554,11 +12168,13 @@
client_ts: 25211748648
client_dur: 44699
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25211763861
server_dur: 18676
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11591,11 +12207,13 @@
client_ts: 25236887649
client_dur: 51265
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25236905107
server_dur: 21519
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11628,11 +12246,13 @@
client_ts: 25262053873
client_dur: 82396
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25262085792
server_dur: 26917
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11665,11 +12285,13 @@
client_ts: 25287387704
client_dur: 103899
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25287423221
server_dur: 43908
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11702,11 +12324,13 @@
client_ts: 25312712971
client_dur: 248879
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25312865501
server_dur: 53943
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11739,11 +12363,13 @@
client_ts: 25338145653
client_dur: 118734
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25338183347
server_dur: 50843
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11776,11 +12402,13 @@
client_ts: 25363427959
client_dur: 127185
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25363473345
server_dur: 52393
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11813,11 +12441,13 @@
client_ts: 25388666272
client_dur: 311561
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25388926887
server_dur: 27556
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -11850,11 +12480,13 @@
client_ts: 25389019468
client_dur: 2257654
client_tid: 537
+ client_pid: 537
server_process: "system_server"
server_thread: "binder:641_2"
server_ts: 25389272037
server_dur: 1993270
server_tid: 656
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -11912,11 +12544,13 @@
client_ts: 25391362853
client_dur: 2138663
client_tid: 537
+ client_pid: 537
server_process: "system_server"
server_thread: "binder:641_1"
server_ts: 25391432268
server_dur: 2057673
server_tid: 655
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -11973,11 +12607,13 @@
client_ts: 25393529331
client_dur: 72907
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25393544112
server_dur: 48279
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12010,11 +12646,13 @@
client_ts: 25418715954
client_dur: 46115
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25418731360
server_dur: 20385
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12047,11 +12685,13 @@
client_ts: 25443850387
client_dur: 44974
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25443866014
server_dur: 19042
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12084,11 +12724,13 @@
client_ts: 25469057379
client_dur: 66877
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25469081511
server_dur: 26836
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12121,11 +12763,13 @@
client_ts: 25494306485
client_dur: 127198
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25494352512
server_dur: 49015
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12158,11 +12802,13 @@
client_ts: 25519756306
client_dur: 101379
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25519800487
server_dur: 31778
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12196,11 +12842,13 @@
client_ts: 25519893501
client_dur: 154940
client_tid: 537
+ client_pid: 537
server_process: "system_server"
server_thread: "binder:641_4"
server_ts: 25519915012
server_dur: 115492
server_tid: 1596
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12234,11 +12882,13 @@
client_ts: 25520078379
client_dur: 176159
client_tid: 537
+ client_pid: 537
server_process: "system_server"
server_thread: "binder:641_1"
server_ts: 25520102430
server_dur: 134309
server_tid: 655
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12272,11 +12922,13 @@
client_ts: 25520281012
client_dur: 123400
client_tid: 537
+ client_pid: 537
server_process: "system_server"
server_thread: "binder:641_2"
server_ts: 25520299524
server_dur: 88243
server_tid: 656
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12309,11 +12961,13 @@
client_ts: 25520423828
client_dur: 343243
client_tid: 537
+ client_pid: 537
server_process: "system_server"
server_thread: "binder:641_3"
server_ts: 25520612948
server_dur: 123445
server_tid: 1595
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12346,11 +13000,13 @@
client_ts: 25520890215
client_dur: 293220
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25521075472
server_dur: 82900
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12384,11 +13040,13 @@
client_ts: 25521216286
client_dur: 489554
client_tid: 537
+ client_pid: 537
server_process: "system_server"
server_thread: "binder:641_3"
server_ts: 25521243526
server_dur: 435659
server_tid: 1595
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -12427,11 +13085,13 @@
client_ts: 25523480228
client_dur: 2277042
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/hwservicemanager"
server_thread: "hwservicemanage"
server_ts: 25523653053
server_dur: 2085804
server_tid: 247
+ server_pid: 247
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -12476,11 +13136,13 @@
client_ts: 25525828575
client_dur: 674113
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/hwservicemanager"
server_thread: "hwservicemanage"
server_ts: 25526007038
server_dur: 466892
server_tid: 247
+ server_pid: 247
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -12525,11 +13187,13 @@
client_ts: 25529470300
client_dur: 103937
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25529493228
server_dur: 62956
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12562,11 +13226,13 @@
client_ts: 25529642910
client_dur: 106592
client_tid: 537
+ client_pid: 537
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25529669348
server_dur: 64544
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12599,11 +13265,13 @@
client_ts: 21610888219
client_dur: 1404460
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21610912981
server_dur: 24345
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12636,11 +13304,13 @@
client_ts: 21713165109
client_dur: 1236372
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21713185409
server_dur: 12103
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12673,11 +13343,13 @@
client_ts: 21817588572
client_dur: 329198
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21817646283
server_dur: 29874
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12710,11 +13382,13 @@
client_ts: 21918044833
client_dur: 54295
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 21918066018
server_dur: 22515
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12747,11 +13421,13 @@
client_ts: 22018230040
client_dur: 4199277
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22018253018
server_dur: 20817
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12784,11 +13460,13 @@
client_ts: 22128615818
client_dur: 66352
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22128641106
server_dur: 21332
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12821,11 +13499,13 @@
client_ts: 22231107021
client_dur: 6202865
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22231126269
server_dur: 21216
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12858,11 +13538,13 @@
client_ts: 22338230784
client_dur: 5927748
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22338257085
server_dur: 22271
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12895,11 +13577,13 @@
client_ts: 22444315008
client_dur: 360477
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22444338001
server_dur: 22884
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12932,11 +13616,13 @@
client_ts: 22545342573
client_dur: 1367091
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22545364958
server_dur: 22936
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -12969,11 +13655,13 @@
client_ts: 22646870376
client_dur: 61414
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22646893001
server_dur: 24570
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13006,11 +13694,13 @@
client_ts: 22747766863
client_dur: 1605566
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22749199929
server_dur: 25123
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13043,11 +13733,13 @@
client_ts: 22849527732
client_dur: 3775048
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22849787260
server_dur: 22559
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13080,11 +13772,13 @@
client_ts: 22955387074
client_dur: 5918097
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 22955504595
server_dur: 12187
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13117,11 +13811,13 @@
client_ts: 23063243768
client_dur: 1153069
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23063268117
server_dur: 21864
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13154,11 +13850,13 @@
client_ts: 23171834613
client_dur: 468230
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23171888187
server_dur: 23659
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13191,11 +13889,13 @@
client_ts: 23274482309
client_dur: 56450
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23274502428
server_dur: 22204
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13228,11 +13928,13 @@
client_ts: 23375517889
client_dur: 2282317
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23377319838
server_dur: 23748
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13265,11 +13967,13 @@
client_ts: 23479410599
client_dur: 60331
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23479434099
server_dur: 24056
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13302,11 +14006,13 @@
client_ts: 23581096165
client_dur: 380036
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23581329034
server_dur: 23039
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13339,11 +14045,13 @@
client_ts: 23683521915
client_dur: 66608
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23683548740
server_dur: 23628
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13376,11 +14084,13 @@
client_ts: 23788017588
client_dur: 110886
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23788091294
server_dur: 22793
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13413,11 +14123,13 @@
client_ts: 23892497829
client_dur: 5298146
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23892520529
server_dur: 12354
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13450,11 +14162,13 @@
client_ts: 23997916363
client_dur: 128256
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 23997934258
server_dur: 22034
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13487,11 +14201,13 @@
client_ts: 24100588444
client_dur: 79761
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24100613596
server_dur: 21941
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13524,11 +14240,13 @@
client_ts: 24203608109
client_dur: 1476962
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24203662175
server_dur: 25824
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13561,11 +14279,13 @@
client_ts: 24305487641
client_dur: 69000
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24305515718
server_dur: 25348
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13598,11 +14318,13 @@
client_ts: 24405940362
client_dur: 114844
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24405962114
server_dur: 22212
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13635,11 +14357,13 @@
client_ts: 24506183075
client_dur: 76130
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24506212466
server_dur: 21817
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13672,11 +14396,13 @@
client_ts: 24606672569
client_dur: 71411
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24606692709
server_dur: 37402
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13709,11 +14435,13 @@
client_ts: 24706847915
client_dur: 77826
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24706871511
server_dur: 21505
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13746,11 +14474,13 @@
client_ts: 24807614065
client_dur: 142762
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24807635682
server_dur: 20956
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13783,11 +14513,13 @@
client_ts: 24909374599
client_dur: 3171973
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24909393940
server_dur: 10997
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13820,11 +14552,13 @@
client_ts: 25012679868
client_dur: 112287
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25012708944
server_dur: 35550
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13857,11 +14591,13 @@
client_ts: 25112924292
client_dur: 43230
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25112938063
server_dur: 18263
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13894,11 +14630,13 @@
client_ts: 25213072326
client_dur: 33395
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25213083753
server_dur: 13289
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13931,11 +14669,13 @@
client_ts: 25313259127
client_dur: 150680
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25313317394
server_dur: 52236
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -13968,11 +14708,13 @@
client_ts: 25415404685
client_dur: 1470768
client_tid: 1225
+ client_pid: 555
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25416823355
server_dur: 22986
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14005,11 +14747,13 @@
client_ts: 25417416478
client_dur: 321332
client_tid: 1225
+ client_pid: 555
server_process: "system_server"
server_thread: "binder:641_4"
server_ts: 25417428728
server_dur: 140719
server_tid: 1596
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14042,11 +14786,13 @@
client_ts: 25867907972
client_dur: 68305
client_tid: 522
+ client_pid: 496
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25867933710
server_dur: 25394
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14079,11 +14825,13 @@
client_ts: 21648847518
client_dur: 138863
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21648864955
server_dur: 110424
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14116,11 +14864,13 @@
client_ts: 21649020222
client_dur: 1298536
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21649025816
server_dur: 1271373
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14153,11 +14903,13 @@
client_ts: 21650405554
client_dur: 21176
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21650412827
server_dur: 7662
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14190,11 +14942,13 @@
client_ts: 21732179696
client_dur: 66330
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21732194327
server_dur: 42279
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14227,11 +14981,13 @@
client_ts: 21732276479
client_dur: 998493
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21732281653
server_dur: 980816
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14264,11 +15020,13 @@
client_ts: 21747805001
client_dur: 32253
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21747815991
server_dur: 13234
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14301,11 +15059,13 @@
client_ts: 21815501160
client_dur: 67864
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21815515197
server_dur: 44624
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14338,11 +15098,13 @@
client_ts: 21815599518
client_dur: 1843570
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21815604505
server_dur: 1825932
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14375,11 +15137,13 @@
client_ts: 21817527536
client_dur: 20911
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21817534229
server_dur: 6822
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14412,11 +15176,13 @@
client_ts: 21898832978
client_dur: 61578
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21898846685
server_dur: 38670
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14449,11 +15215,13 @@
client_ts: 21898923783
client_dur: 1096630
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21898928634
server_dur: 1080195
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14486,11 +15254,13 @@
client_ts: 21914447745
client_dur: 30172
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21914458873
server_dur: 11417
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14523,11 +15293,13 @@
client_ts: 21982278493
client_dur: 137675
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21982310594
server_dur: 80114
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14560,11 +15332,13 @@
client_ts: 21982477699
client_dur: 1235182
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21982492293
server_dur: 1187140
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14597,11 +15371,13 @@
client_ts: 21983894427
client_dur: 56732
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 21983913100
server_dur: 18080
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14634,11 +15410,13 @@
client_ts: 22065483496
client_dur: 63685
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22065497670
server_dur: 40803
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14671,11 +15449,13 @@
client_ts: 22065575735
client_dur: 1062604
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22065580382
server_dur: 1045862
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14708,11 +15488,13 @@
client_ts: 22081125903
client_dur: 31676
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22081137566
server_dur: 12008
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14745,11 +15527,13 @@
client_ts: 22148826292
client_dur: 66432
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22148840763
server_dur: 42889
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14782,11 +15566,13 @@
client_ts: 22148922210
client_dur: 1055199
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22148927117
server_dur: 1037009
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14819,11 +15605,13 @@
client_ts: 22150072810
client_dur: 21373
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22150080025
server_dur: 7715
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14856,11 +15644,13 @@
client_ts: 22232166904
client_dur: 64562
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22232181958
server_dur: 40112
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14893,11 +15683,13 @@
client_ts: 22232260319
client_dur: 1084947
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22232265525
server_dur: 1065811
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14930,11 +15722,13 @@
client_ts: 22247787616
client_dur: 29515
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22247797746
server_dur: 12125
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -14967,11 +15761,13 @@
client_ts: 22315503408
client_dur: 75460
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22315519682
server_dur: 49022
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15004,11 +15800,13 @@
client_ts: 22315610938
client_dur: 1046448
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22315616049
server_dur: 1029776
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15041,11 +15839,13 @@
client_ts: 22316735903
client_dur: 21152
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22316742808
server_dur: 7783
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15078,11 +15878,13 @@
client_ts: 22398839076
client_dur: 65963
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22398854027
server_dur: 42248
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15115,11 +15917,13 @@
client_ts: 22398960806
client_dur: 1018998
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22398966568
server_dur: 1000410
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15152,11 +15956,13 @@
client_ts: 22414462930
client_dur: 32955
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22414474372
server_dur: 13302
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15189,11 +15995,13 @@
client_ts: 22482179365
client_dur: 71661
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22482194253
server_dur: 47932
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15226,11 +16034,13 @@
client_ts: 22482282793
client_dur: 955159
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22482287911
server_dur: 938324
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15263,11 +16073,13 @@
client_ts: 22497465809
client_dur: 39624
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22497477915
server_dur: 17691
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15300,11 +16112,13 @@
client_ts: 22565521231
client_dur: 66993
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22565536155
server_dur: 42982
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15337,11 +16151,13 @@
client_ts: 22565618391
client_dur: 1026658
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22565623264
server_dur: 1009748
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15374,11 +16190,13 @@
client_ts: 22581241130
client_dur: 37185
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22581254325
server_dur: 15879
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15411,11 +16229,13 @@
client_ts: 22648855410
client_dur: 78080
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22648872617
server_dur: 51463
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15448,11 +16268,13 @@
client_ts: 22648965876
client_dur: 1080456
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22648971095
server_dur: 1061465
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15485,11 +16307,13 @@
client_ts: 22650134321
client_dur: 21145
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22650140974
server_dur: 7869
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15522,11 +16346,13 @@
client_ts: 22732183976
client_dur: 84922
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22732199541
server_dur: 59268
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15559,11 +16385,13 @@
client_ts: 22732300442
client_dur: 1084256
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22732305487
server_dur: 1066498
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15596,11 +16424,13 @@
client_ts: 22749316211
client_dur: 37389
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22749329367
server_dur: 15449
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15633,11 +16463,13 @@
client_ts: 22815554390
client_dur: 80259
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22815571850
server_dur: 52908
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15670,11 +16502,13 @@
client_ts: 22815665677
client_dur: 1846724
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22815670690
server_dur: 1827939
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15707,11 +16541,13 @@
client_ts: 22817599826
client_dur: 21169
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22817606552
server_dur: 8080
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15744,11 +16580,13 @@
client_ts: 22898837991
client_dur: 66016
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22898853740
server_dur: 41111
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15781,11 +16619,13 @@
client_ts: 22898932620
client_dur: 1881472
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22898937509
server_dur: 1862476
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15818,11 +16658,13 @@
client_ts: 22914460532
client_dur: 34598
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22914472324
server_dur: 14518
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15855,11 +16697,13 @@
client_ts: 22982182870
client_dur: 80394
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22982200371
server_dur: 52999
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15892,11 +16736,13 @@
client_ts: 22982296391
client_dur: 1052212
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22982301600
server_dur: 1033314
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15929,11 +16775,13 @@
client_ts: 22983445756
client_dur: 23169
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 22983452175
server_dur: 10357
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -15966,11 +16814,13 @@
client_ts: 23065513683
client_dur: 74423
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23065529019
server_dur: 49067
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16003,11 +16853,13 @@
client_ts: 23065619219
client_dur: 1146958
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23065624303
server_dur: 1129990
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16040,11 +16892,13 @@
client_ts: 23081285291
client_dur: 45213
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23081307603
server_dur: 14325
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16077,11 +16931,13 @@
client_ts: 23148835709
client_dur: 76791
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23148852272
server_dur: 50863
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16114,11 +16970,13 @@
client_ts: 23148944247
client_dur: 1986947
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23148949481
server_dur: 1965225
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16151,11 +17009,13 @@
client_ts: 23151027818
client_dur: 25087
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23151036483
server_dur: 9385
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16188,11 +17048,13 @@
client_ts: 23232183799
client_dur: 75511
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23232201226
server_dur: 48102
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16225,11 +17087,13 @@
client_ts: 23232290686
client_dur: 1140969
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23232295646
server_dur: 1123404
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16262,11 +17126,13 @@
client_ts: 23249891699
client_dur: 37797
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23249904526
server_dur: 16397
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16299,11 +17165,13 @@
client_ts: 23315566931
client_dur: 110557
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23315592450
server_dur: 69421
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16336,11 +17204,13 @@
client_ts: 23315722066
client_dur: 2606042
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23315729839
server_dur: 2583671
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16373,11 +17243,13 @@
client_ts: 23318420005
client_dur: 21345
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23318427118
server_dur: 7958
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16410,11 +17282,13 @@
client_ts: 23398873863
client_dur: 68770
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23398889934
server_dur: 41798
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16447,11 +17321,13 @@
client_ts: 23398973230
client_dur: 1176570
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23398978271
server_dur: 1158688
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16484,11 +17360,13 @@
client_ts: 23416727246
client_dur: 33867
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23416739503
server_dur: 14319
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16521,11 +17399,13 @@
client_ts: 23482185608
client_dur: 80279
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23482202317
server_dur: 53655
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16558,11 +17438,13 @@
client_ts: 23482297909
client_dur: 1040841
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23482303086
server_dur: 1022859
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16595,11 +17477,13 @@
client_ts: 23483420403
client_dur: 20295
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23483427104
server_dur: 6793
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16632,11 +17516,13 @@
client_ts: 23566095373
client_dur: 80168
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23566112317
server_dur: 53405
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16669,11 +17555,13 @@
client_ts: 23566207004
client_dur: 1080032
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23566212869
server_dur: 1062341
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16706,11 +17594,13 @@
client_ts: 23581426699
client_dur: 33178
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23581438242
server_dur: 13572
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16743,11 +17633,13 @@
client_ts: 23648877211
client_dur: 74827
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23648892093
server_dur: 50840
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16780,11 +17672,13 @@
client_ts: 23648984124
client_dur: 1869563
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23648989106
server_dur: 1850394
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16817,11 +17711,13 @@
client_ts: 23650943350
client_dur: 22389
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23650950419
server_dur: 8699
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16854,11 +17750,13 @@
client_ts: 23732162997
client_dur: 66948
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23732178223
server_dur: 42065
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16891,11 +17789,13 @@
client_ts: 23732260275
client_dur: 1099825
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23732265173
server_dur: 1083011
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16928,11 +17828,13 @@
client_ts: 23747796852
client_dur: 29683
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23747806637
server_dur: 12580
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -16965,11 +17867,13 @@
client_ts: 23815516337
client_dur: 68846
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23815530730
server_dur: 44894
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17002,11 +17906,13 @@
client_ts: 23815619259
client_dur: 986718
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23815623956
server_dur: 969888
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17039,11 +17945,13 @@
client_ts: 23816691292
client_dur: 20206
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23816697719
server_dur: 7427
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17076,11 +17984,13 @@
client_ts: 23898849538
client_dur: 73093
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23898865505
server_dur: 44882
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17113,11 +18023,13 @@
client_ts: 23898957000
client_dur: 1065096
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23898962241
server_dur: 1045751
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17150,11 +18062,13 @@
client_ts: 23914455173
client_dur: 29880
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23914466130
server_dur: 11108
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17187,11 +18101,13 @@
client_ts: 23982180549
client_dur: 85583
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23982199040
server_dur: 52914
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17224,11 +18140,13 @@
client_ts: 23982305851
client_dur: 1744711
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23982314504
server_dur: 1722762
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17261,11 +18179,13 @@
client_ts: 23984133705
client_dur: 20045
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 23984139858
server_dur: 7402
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17298,11 +18218,13 @@
client_ts: 24065542758
client_dur: 68668
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24065557894
server_dur: 43859
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17335,11 +18257,13 @@
client_ts: 24065652205
client_dur: 1049759
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24065657696
server_dur: 1032583
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17372,11 +18296,13 @@
client_ts: 24081125997
client_dur: 31826
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24081137112
server_dur: 13041
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17409,11 +18335,13 @@
client_ts: 24148820113
client_dur: 68214
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24148833979
server_dur: 44630
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17446,11 +18374,13 @@
client_ts: 24148918715
client_dur: 1009266
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24148923375
server_dur: 991906
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17483,11 +18413,13 @@
client_ts: 24150011467
client_dur: 21064
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24150018449
server_dur: 7359
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17520,11 +18452,13 @@
client_ts: 24247778973
client_dur: 34911
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24247791507
server_dur: 14684
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17557,11 +18491,13 @@
client_ts: 24248842389
client_dur: 66174
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24248855559
server_dur: 43223
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17594,11 +18530,13 @@
client_ts: 24248937934
client_dur: 1130965
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24248943066
server_dur: 1111247
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17631,11 +18569,13 @@
client_ts: 24250153754
client_dur: 21489
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24250161172
server_dur: 7362
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17668,11 +18608,13 @@
client_ts: 24332164030
client_dur: 78622
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24332193334
server_dur: 39186
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17705,11 +18647,13 @@
client_ts: 24332271286
client_dur: 1233475
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24332276288
server_dur: 1215090
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17742,11 +18686,13 @@
client_ts: 24350341616
client_dur: 97785
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24350364644
server_dur: 50768
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17779,11 +18725,13 @@
client_ts: 24415506341
client_dur: 73094
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24415521413
server_dur: 48860
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17816,11 +18764,13 @@
client_ts: 24415610395
client_dur: 1963175
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24415614985
server_dur: 1944970
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17853,11 +18803,13 @@
client_ts: 24417688619
client_dur: 22666
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24417696179
server_dur: 8868
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17890,11 +18842,13 @@
client_ts: 24498858408
client_dur: 72316
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24498874905
server_dur: 44364
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17927,11 +18881,13 @@
client_ts: 24498965251
client_dur: 2212172
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24498971364
server_dur: 2189623
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -17964,11 +18920,13 @@
client_ts: 24514530326
client_dur: 46445
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24514545922
server_dur: 16967
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18001,11 +18959,13 @@
client_ts: 24582239101
client_dur: 102168
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24582262241
server_dur: 62646
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18038,11 +18998,13 @@
client_ts: 24582383933
client_dur: 1125278
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24582393122
server_dur: 1094530
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18075,11 +19037,13 @@
client_ts: 24583627699
client_dur: 36229
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24583638897
server_dur: 12637
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18112,11 +19076,13 @@
client_ts: 24665516749
client_dur: 77492
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24665535013
server_dur: 46956
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18149,11 +19115,13 @@
client_ts: 24665629297
client_dur: 1056190
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24665650779
server_dur: 1018462
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18186,11 +19154,13 @@
client_ts: 24681436859
client_dur: 36053
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24681447493
server_dur: 17169
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18223,11 +19193,13 @@
client_ts: 24748868138
client_dur: 84885
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24748886644
server_dur: 54090
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18260,11 +19232,13 @@
client_ts: 24748988510
client_dur: 1030023
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24748994792
server_dur: 1007690
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18297,11 +19271,13 @@
client_ts: 24750114696
client_dur: 25844
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24750122620
server_dur: 9559
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18334,11 +19310,13 @@
client_ts: 24832172264
client_dur: 71964
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24832186234
server_dur: 48177
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18371,11 +19349,13 @@
client_ts: 24832278767
client_dur: 2319199
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24832284387
server_dur: 2299722
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18408,11 +19388,13 @@
client_ts: 24848194066
client_dur: 38990
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24848207084
server_dur: 16882
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18445,11 +19427,13 @@
client_ts: 24915569035
client_dur: 92319
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24915587307
server_dur: 61522
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18482,11 +19466,13 @@
client_ts: 24915703770
client_dur: 1154960
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24915710935
server_dur: 1133005
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18519,11 +19505,13 @@
client_ts: 24916964211
client_dur: 24607
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24916971111
server_dur: 10684
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18556,11 +19544,13 @@
client_ts: 24998945706
client_dur: 111229
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24998970836
server_dur: 66036
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18593,11 +19583,13 @@
client_ts: 24999109626
client_dur: 1079778
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 24999121401
server_dur: 1042002
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18630,11 +19622,13 @@
client_ts: 25014488039
client_dur: 70943
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25014504840
server_dur: 24296
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18667,11 +19661,13 @@
client_ts: 25082202078
client_dur: 73854
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25082217860
server_dur: 47920
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18704,11 +19700,13 @@
client_ts: 25082306875
client_dur: 1782258
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25082312116
server_dur: 1764384
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18741,11 +19739,13 @@
client_ts: 25084166020
client_dur: 20222
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25084172595
server_dur: 7394
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18778,11 +19778,13 @@
client_ts: 25165504670
client_dur: 81307
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25165518960
server_dur: 55941
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18815,11 +19817,13 @@
client_ts: 25165619958
client_dur: 997114
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25165625294
server_dur: 978831
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18852,11 +19856,13 @@
client_ts: 25181108704
client_dur: 38312
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25181120018
server_dur: 17603
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18889,11 +19895,13 @@
client_ts: 25248839993
client_dur: 71834
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25248855062
server_dur: 47208
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18926,11 +19934,13 @@
client_ts: 25248942032
client_dur: 1065822
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25248946700
server_dur: 1047977
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -18963,11 +19973,13 @@
client_ts: 25250092465
client_dur: 21121
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25250099244
server_dur: 7872
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19000,11 +20012,13 @@
client_ts: 25332433123
client_dur: 129185
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25332463293
server_dur: 75363
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19037,11 +20051,13 @@
client_ts: 25332622145
client_dur: 3970213
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25332636462
server_dur: 3919134
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19074,11 +20090,13 @@
client_ts: 25347937130
client_dur: 63143
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25347956107
server_dur: 23630
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19111,11 +20129,13 @@
client_ts: 25415532955
client_dur: 74958
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25415548486
server_dur: 48910
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19148,11 +20168,13 @@
client_ts: 25415639063
client_dur: 1045725
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25415643854
server_dur: 1028657
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19185,11 +20207,13 @@
client_ts: 25416779828
client_dur: 22459
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25416786530
server_dur: 8393
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19222,11 +20246,13 @@
client_ts: 25499090883
client_dur: 135524
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25499122517
server_dur: 77879
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19259,11 +20285,13 @@
client_ts: 25499287661
client_dur: 1179689
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25499301640
server_dur: 1130895
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19296,11 +20324,13 @@
client_ts: 25514592061
client_dur: 62604
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25514612449
server_dur: 22109
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19333,11 +20363,13 @@
client_ts: 25582338627
client_dur: 162705
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25582368275
server_dur: 92253
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19370,11 +20402,13 @@
client_ts: 25582559609
client_dur: 1051443
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25582572935
server_dur: 992794
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19407,11 +20441,13 @@
client_ts: 25583792668
client_dur: 57270
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25583811204
server_dur: 18520
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19444,11 +20480,13 @@
client_ts: 25665575887
client_dur: 98551
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25665594994
server_dur: 67512
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19481,11 +20519,13 @@
client_ts: 25665714191
client_dur: 2056246
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25665719790
server_dur: 2036405
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19518,11 +20558,13 @@
client_ts: 25681400816
client_dur: 89610
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25681427461
server_dur: 37612
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19555,11 +20597,13 @@
client_ts: 25748935127
client_dur: 126067
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25748964935
server_dur: 75428
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19592,11 +20636,13 @@
client_ts: 25749129537
client_dur: 1130001
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25749140148
server_dur: 1092654
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19629,11 +20675,13 @@
client_ts: 25750403211
client_dur: 43991
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25750417428
server_dur: 15659
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19666,11 +20714,13 @@
client_ts: 25832201262
client_dur: 76032
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25832217990
server_dur: 49551
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19703,11 +20753,13 @@
client_ts: 25832312368
client_dur: 1052337
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25832317105
server_dur: 1035144
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19740,11 +20792,13 @@
client_ts: 25847799175
client_dur: 40678
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25847812958
server_dur: 17906
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19777,11 +20831,13 @@
client_ts: 25855749248
client_dur: 31727
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25855758456
server_dur: 14151
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19814,11 +20870,13 @@
client_ts: 25865415841
client_dur: 46578
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25865424168
server_dur: 29991
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19851,11 +20909,13 @@
client_ts: 25865488539
client_dur: 1091161
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25865493112
server_dur: 1074785
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19888,11 +20948,13 @@
client_ts: 25882229417
client_dur: 49798
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25882240791
server_dur: 29545
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19925,11 +20987,13 @@
client_ts: 25882302427
client_dur: 976002
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25882306957
server_dur: 960192
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19962,11 +21026,13 @@
client_ts: 25915516257
client_dur: 67861
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25915531128
server_dur: 43477
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -19999,11 +21065,13 @@
client_ts: 25915614740
client_dur: 879798
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25915619820
server_dur: 861862
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20036,11 +21104,13 @@
client_ts: 25947791827
client_dur: 36462
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25947803365
server_dur: 16366
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20073,11 +21143,13 @@
client_ts: 25965634137
client_dur: 62809
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25965647687
server_dur: 39248
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20110,11 +21182,13 @@
client_ts: 25965727363
client_dur: 1082911
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25965732380
server_dur: 1065715
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20147,11 +21221,13 @@
client_ts: 25966880090
client_dur: 18647
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25966885882
server_dur: 6742
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20184,11 +21260,13 @@
client_ts: 25998857609
client_dur: 68802
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25998873383
server_dur: 43179
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20221,11 +21299,13 @@
client_ts: 25998956453
client_dur: 896029
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 25998961673
server_dur: 878692
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20258,11 +21338,13 @@
client_ts: 26064480113
client_dur: 41059
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26064494262
server_dur: 17230
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20295,11 +21377,13 @@
client_ts: 26082167007
client_dur: 68814
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26082181896
server_dur: 44307
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20332,11 +21416,13 @@
client_ts: 26082265345
client_dur: 984160
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26082270124
server_dur: 967726
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20369,11 +21455,13 @@
client_ts: 26083328041
client_dur: 20356
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26083334137
server_dur: 7873
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20406,11 +21494,13 @@
client_ts: 26165543672
client_dur: 76748
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26165564279
server_dur: 46139
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20443,11 +21533,13 @@
client_ts: 26165664730
client_dur: 952016
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26165670566
server_dur: 934833
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20480,11 +21572,13 @@
client_ts: 26181134030
client_dur: 39663
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26181147708
server_dur: 17312
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20517,11 +21611,13 @@
client_ts: 26265553005
client_dur: 106037
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26265570929
server_dur: 76133
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20554,11 +21650,13 @@
client_ts: 26265695797
client_dur: 1070288
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26265701257
server_dur: 1051768
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20591,11 +21689,13 @@
client_ts: 26266851930
client_dur: 21080
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26266858935
server_dur: 7493
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20628,11 +21728,13 @@
client_ts: 26348993760
client_dur: 74635
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26349012914
server_dur: 45210
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20665,11 +21767,13 @@
client_ts: 26349100408
client_dur: 985507
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26349105368
server_dur: 967525
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20702,11 +21806,13 @@
client_ts: 26364884926
client_dur: 48465
client_tid: 496
+ client_pid: 496
server_process: "/vendor/bin/hw/android.hardware.graphics.composer3-service.ranchu"
server_thread: "binder:446_1"
server_ts: 26364907480
server_dur: 16844
server_tid: 507
+ server_pid: 446
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20739,11 +21845,13 @@
client_ts: 25527594973
client_dur: 961513
client_tid: 431
+ client_pid: 431
server_process: "system_server"
server_thread: "system_server"
server_ts: 25528486848
server_dur: 41164
server_tid: 641
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20776,11 +21884,13 @@
client_ts: 25519230900
client_dur: 67687
client_tid: 458
+ client_pid: 458
server_process: "system_server"
server_thread: "system-server-i"
server_ts: 25519257217
server_dur: 19303
server_tid: 665
+ server_pid: 641
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20813,11 +21923,13 @@
client_ts: 25887934200
client_dur: 73511
client_tid: 1625
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.input.processor-service.example"
server_thread: "android.hardwar"
server_ts: 25887963950
server_dur: 31341
server_tid: 447
+ server_pid: 447
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20850,11 +21962,13 @@
client_ts: 25924014206
client_dur: 48397
client_tid: 1625
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.input.processor-service.example"
server_thread: "android.hardwar"
server_ts: 25924032607
server_dur: 19471
server_tid: 447
+ server_pid: 447
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20887,11 +22001,13 @@
client_ts: 25924552433
client_dur: 51388
client_tid: 1625
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.input.processor-service.example"
server_thread: "android.hardwar"
server_ts: 25924572649
server_dur: 16951
server_tid: 447
+ server_pid: 447
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20924,11 +22040,13 @@
client_ts: 25925236390
client_dur: 40800
client_tid: 1625
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.input.processor-service.example"
server_thread: "android.hardwar"
server_ts: 25925252802
server_dur: 11692
server_tid: 447
+ server_pid: 447
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20961,11 +22079,13 @@
client_ts: 25925312006
client_dur: 22098
client_tid: 1625
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.input.processor-service.example"
server_thread: "android.hardwar"
server_ts: 25925321018
server_dur: 4977
server_tid: 447
+ server_pid: 447
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -20998,11 +22118,13 @@
client_ts: 25925340685
client_dur: 18485
client_tid: 1625
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.input.processor-service.example"
server_thread: "android.hardwar"
server_ts: 25925348223
server_dur: 3660
server_tid: 447
+ server_pid: 447
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21035,11 +22157,13 @@
client_ts: 25925364763
client_dur: 18634
client_tid: 1625
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.input.processor-service.example"
server_thread: "android.hardwar"
server_ts: 25925372247
server_dur: 3490
server_tid: 447
+ server_pid: 447
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21072,11 +22196,13 @@
client_ts: 26046721012
client_dur: 137219
client_tid: 1625
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.input.processor-service.example"
server_thread: "android.hardwar"
server_ts: 26046826730
server_dur: 20407
server_tid: 447
+ server_pid: 447
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21109,11 +22235,13 @@
client_ts: 25848902022
client_dur: 109438
client_tid: 662
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25848918031
server_dur: 71184
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21147,11 +22275,13 @@
client_ts: 25849035817
client_dur: 85138
client_tid: 662
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25849046771
server_dur: 23591
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21184,11 +22314,13 @@
client_ts: 25965522657
client_dur: 87636
client_tid: 662
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25965536704
server_dur: 31166
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -21221,11 +22353,13 @@
client_ts: 26046475353
client_dur: 139999
client_tid: 662
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 26046494430
server_dur: 36023
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21252,11 +22386,13 @@
client_ts: 26049659202
client_dur: 66793
client_tid: 662
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 26049676304
server_dur: 21699
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21283,11 +22419,13 @@
client_ts: 25852597933
client_dur: 72360
client_tid: 663
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25852614647
server_dur: 40436
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21321,11 +22459,13 @@
client_ts: 25852691734
client_dur: 40316
client_tid: 663
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25852702316
server_dur: 18235
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21358,11 +22498,13 @@
client_ts: 25851140935
client_dur: 82845
client_tid: 661
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25851157134
server_dur: 45749
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21396,11 +22538,13 @@
client_ts: 25851245190
client_dur: 40441
client_tid: 661
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25851255329
server_dur: 18715
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21434,11 +22578,13 @@
client_ts: 25854136251
client_dur: 140850
client_tid: 661
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25854153001
server_dur: 42359
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21471,11 +22617,13 @@
client_ts: 25982476503
client_dur: 71952
client_tid: 660
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25982503060
server_dur: 29743
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21508,11 +22656,13 @@
client_ts: 25873131715
client_dur: 117082
client_tid: 659
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25873153628
server_dur: 22969
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21539,11 +22689,13 @@
client_ts: 25883734665
client_dur: 152980
client_tid: 659
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25883839992
server_dur: 25887
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21576,11 +22728,13 @@
client_ts: 25537922715
client_dur: 260041
client_tid: 1600
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.lights-service.example"
server_thread: "android.hardwar"
server_ts: 25537947459
server_dur: 137623
server_tid: 448
+ server_pid: 448
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21608,11 +22762,13 @@
client_ts: 25285800698
client_dur: 1963972
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25285972364
server_dur: 1764197
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -21670,11 +22826,13 @@
client_ts: 25359359930
client_dur: 58056845
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25359406757
server_dur: 57997245
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -21726,11 +22884,13 @@
client_ts: 25417583831
client_dur: 159127
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25417600127
server_dur: 117766
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21764,11 +22924,13 @@
client_ts: 25417795254
client_dur: 84143
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25417807548
server_dur: 52980
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21802,11 +22964,13 @@
client_ts: 25417900256
client_dur: 72685
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25417909455
server_dur: 47502
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21840,11 +23004,13 @@
client_ts: 25417989778
client_dur: 70644
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25418000174
server_dur: 44675
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21878,11 +23044,13 @@
client_ts: 25418084967
client_dur: 63335
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25418094122
server_dur: 43952
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21916,11 +23084,13 @@
client_ts: 25418162868
client_dur: 73089
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25418174366
server_dur: 51193
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21954,11 +23124,13 @@
client_ts: 25418257945
client_dur: 71217
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25418268205
server_dur: 50582
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -21992,11 +23164,13 @@
client_ts: 25418344237
client_dur: 68933
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25418354448
server_dur: 48033
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22030,11 +23204,13 @@
client_ts: 25418434003
client_dur: 70051
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25418444322
server_dur: 49218
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22068,11 +23244,13 @@
client_ts: 25418523244
client_dur: 71860
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25418533528
server_dur: 51097
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22106,11 +23284,13 @@
client_ts: 25418613235
client_dur: 80217
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25418623429
server_dur: 59922
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22144,11 +23324,13 @@
client_ts: 25418707467
client_dur: 100848
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25418716983
server_dur: 80176
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22182,11 +23364,13 @@
client_ts: 25418859801
client_dur: 96287
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25418874922
server_dur: 66129
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22220,11 +23404,13 @@
client_ts: 25418990456
client_dur: 73140
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419002227
server_dur: 50140
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22258,11 +23444,13 @@
client_ts: 25419082851
client_dur: 69691
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419093189
server_dur: 48614
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22296,11 +23484,13 @@
client_ts: 25419197218
client_dur: 97019
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419208385
server_dur: 75308
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22334,11 +23524,13 @@
client_ts: 25419309331
client_dur: 68503
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419319559
server_dur: 48070
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22372,11 +23564,13 @@
client_ts: 25419402979
client_dur: 68957
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419413041
server_dur: 48592
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22410,11 +23604,13 @@
client_ts: 25419490548
client_dur: 70455
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419500948
server_dur: 49673
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22448,11 +23644,13 @@
client_ts: 25419576883
client_dur: 68126
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419587154
server_dur: 47213
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22486,11 +23684,13 @@
client_ts: 25419662926
client_dur: 68985
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419673103
server_dur: 48313
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22524,11 +23724,13 @@
client_ts: 25419747914
client_dur: 70204
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419758511
server_dur: 49425
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22562,11 +23764,13 @@
client_ts: 25419838530
client_dur: 74294
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419851530
server_dur: 50943
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22600,11 +23804,13 @@
client_ts: 25419930878
client_dur: 71254
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25419941349
server_dur: 50447
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22638,11 +23844,13 @@
client_ts: 25420022065
client_dur: 70064
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420034446
server_dur: 47514
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22676,11 +23884,13 @@
client_ts: 25420107549
client_dur: 67997
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420117365
server_dur: 47959
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22714,11 +23924,13 @@
client_ts: 25420191395
client_dur: 67798
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420201429
server_dur: 47599
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22752,11 +23964,13 @@
client_ts: 25420275173
client_dur: 68378
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420285912
server_dur: 47561
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22790,11 +24004,13 @@
client_ts: 25420359212
client_dur: 68447
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420369692
server_dur: 47721
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22828,11 +24044,13 @@
client_ts: 25420458125
client_dur: 69217
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420468424
server_dur: 48683
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22866,11 +24084,13 @@
client_ts: 25420542827
client_dur: 68982
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420553053
server_dur: 48593
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22904,11 +24124,13 @@
client_ts: 25420642092
client_dur: 75336
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420652418
server_dur: 54692
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22942,11 +24164,13 @@
client_ts: 25420732600
client_dur: 66989
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420742486
server_dur: 46762
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -22980,11 +24204,13 @@
client_ts: 25420814670
client_dur: 66733
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420824622
server_dur: 46663
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23018,11 +24244,13 @@
client_ts: 25420898454
client_dur: 67283
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420908490
server_dur: 47258
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23056,11 +24284,13 @@
client_ts: 25420980515
client_dur: 68119
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25420990555
server_dur: 47881
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23094,11 +24324,13 @@
client_ts: 25421062960
client_dur: 67691
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25421073099
server_dur: 47279
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23132,11 +24364,13 @@
client_ts: 25421149398
client_dur: 67456
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25421159582
server_dur: 46812
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23170,11 +24404,13 @@
client_ts: 25421234249
client_dur: 102474
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25421244402
server_dur: 81689
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23208,11 +24444,13 @@
client_ts: 25421351001
client_dur: 68629
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25421361736
server_dur: 50268
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23246,11 +24484,13 @@
client_ts: 25421437438
client_dur: 78505
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25421447770
server_dur: 60705
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23284,11 +24524,13 @@
client_ts: 25421529017
client_dur: 90619
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25421536869
server_dur: 70139
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23322,11 +24564,13 @@
client_ts: 25421667924
client_dur: 93173
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25421681338
server_dur: 67854
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23360,11 +24604,13 @@
client_ts: 25421792054
client_dur: 79868
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25421807359
server_dur: 55975
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23398,11 +24644,13 @@
client_ts: 25421889199
client_dur: 85495
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25421897198
server_dur: 65834
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23436,11 +24684,13 @@
client_ts: 25422008441
client_dur: 90387
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25422024828
server_dur: 62034
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23474,11 +24724,13 @@
client_ts: 25422133767
client_dur: 75807
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25422147676
server_dur: 51244
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23512,11 +24764,13 @@
client_ts: 25422225432
client_dur: 98464
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25422233734
server_dur: 79168
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23550,11 +24804,13 @@
client_ts: 25422355100
client_dur: 93353
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25422370044
server_dur: 64908
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23588,11 +24844,13 @@
client_ts: 25422488580
client_dur: 81077
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25422503734
server_dur: 56902
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23626,11 +24884,13 @@
client_ts: 25422585669
client_dur: 81637
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25422593474
server_dur: 62945
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23664,11 +24924,13 @@
client_ts: 25422698364
client_dur: 307058
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25422912325
server_dur: 72852
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23702,11 +24964,13 @@
client_ts: 25423038416
client_dur: 85760
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25423050636
server_dur: 59617
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23740,11 +25004,13 @@
client_ts: 25423141970
client_dur: 65309
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25423147589
server_dur: 46373
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23778,11 +25044,13 @@
client_ts: 25423222741
client_dur: 83982
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25423241349
server_dur: 52179
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23816,11 +25084,13 @@
client_ts: 25423321767
client_dur: 84883
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25423330170
server_dur: 64541
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23854,11 +25124,13 @@
client_ts: 25423444205
client_dur: 97794
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25423460614
server_dur: 64145
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23892,11 +25164,13 @@
client_ts: 25423571069
client_dur: 79325
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25423585310
server_dur: 56042
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23930,11 +25204,13 @@
client_ts: 25423667089
client_dur: 80196
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25423674807
server_dur: 61267
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -23968,11 +25244,13 @@
client_ts: 25423778912
client_dur: 85732
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25423789294
server_dur: 63712
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24006,11 +25284,13 @@
client_ts: 25423899033
client_dur: 83874
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25423913207
server_dur: 61126
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24044,11 +25324,13 @@
client_ts: 25423999018
client_dur: 80807
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25424006723
server_dur: 62351
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24082,11 +25364,13 @@
client_ts: 25424119494
client_dur: 90723
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25424133267
server_dur: 65314
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24120,11 +25404,13 @@
client_ts: 25424244832
client_dur: 75424
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25424257485
server_dur: 54108
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24158,11 +25444,13 @@
client_ts: 25424340551
client_dur: 68134
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25424352371
server_dur: 47952
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24196,11 +25484,13 @@
client_ts: 25424423268
client_dur: 79235
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25424430889
server_dur: 60700
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24234,11 +25524,13 @@
client_ts: 25424532071
client_dur: 132824
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25424548055
server_dur: 63569
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24272,11 +25564,13 @@
client_ts: 25424695404
client_dur: 78895
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25424709439
server_dur: 55753
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24310,11 +25604,13 @@
client_ts: 25424790712
client_dur: 84106
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25424798759
server_dur: 65429
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24348,11 +25644,13 @@
client_ts: 25424904112
client_dur: 86631
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_3"
server_ts: 25424916724
server_dur: 62466
server_tid: 1590
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24386,11 +25684,13 @@
client_ts: 25425012627
client_dur: 82418
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25425020923
server_dur: 61511
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24424,11 +25724,13 @@
client_ts: 25425134890
client_dur: 80492
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25425151484
server_dur: 55304
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24462,11 +25764,13 @@
client_ts: 25425231522
client_dur: 103387
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25425239219
server_dur: 85661
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -24506,11 +25810,13 @@
client_ts: 25425372618
client_dur: 91185
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25425384448
server_dur: 68305
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24544,11 +25850,13 @@
client_ts: 25425498321
client_dur: 82574
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25425511999
server_dur: 60168
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24582,11 +25890,13 @@
client_ts: 25425597030
client_dur: 96570
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25425604832
server_dur: 77508
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24620,11 +25930,13 @@
client_ts: 25425734906
client_dur: 90504
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25425748243
server_dur: 65377
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24658,11 +25970,13 @@
client_ts: 25425853178
client_dur: 75664
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25425868250
server_dur: 50805
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24696,11 +26010,13 @@
client_ts: 25425949096
client_dur: 75914
client_tid: 1591
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25425967109
server_dur: 49564
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24733,11 +26049,13 @@
client_ts: 25507770941
client_dur: 659345
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25507817302
server_dur: 493959
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24764,11 +26082,13 @@
client_ts: 25508483480
client_dur: 113431
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25508520735
server_dur: 37596
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24795,11 +26115,13 @@
client_ts: 25512346526
client_dur: 247626
client_tid: 665
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.sensors-service.example"
server_thread: "android.hardwar"
server_ts: 25512379433
server_dur: 68665
server_tid: 458
+ server_pid: 458
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24832,11 +26154,13 @@
client_ts: 25519832521
client_dur: 244039
client_tid: 665
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.sensors-service.example"
server_thread: "android.hardwar"
server_ts: 25519857925
server_dur: 186450
server_tid: 458
+ server_pid: 458
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24863,11 +26187,13 @@
client_ts: 25520140841
client_dur: 73832
client_tid: 665
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.sensors-service.example"
server_thread: "android.hardwar"
server_ts: 25520164682
server_dur: 18571
server_tid: 458
+ server_pid: 458
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24894,11 +26220,13 @@
client_ts: 25523026906
client_dur: 340409
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25523191948
server_dur: 40297
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24931,11 +26259,13 @@
client_ts: 25524188687
client_dur: 89696
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25524226273
server_dur: 31748
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -24968,11 +26298,13 @@
client_ts: 25524630643
client_dur: 80450
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25524666614
server_dur: 25632
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25005,11 +26337,13 @@
client_ts: 25524881306
client_dur: 64099
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25524906781
server_dur: 18982
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25042,11 +26376,13 @@
client_ts: 25525155622
client_dur: 182063
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25525206343
server_dur: 111535
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25079,11 +26415,13 @@
client_ts: 25886972081
client_dur: 392512
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/hwservicemanager"
server_thread: "hwservicemanage"
server_ts: 25887243579
server_dur: 100309
server_tid: 247
+ server_pid: 247
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25116,11 +26454,13 @@
client_ts: 25887384160
client_dur: 146196
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/hwservicemanager"
server_thread: "hwservicemanage"
server_ts: 25887501006
server_dur: 15631
server_tid: 247
+ server_pid: 247
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25153,11 +26493,13 @@
client_ts: 25887600584
client_dur: 263828
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/hwservicemanager"
server_thread: "hwservicemanage"
server_ts: 25887779478
server_dur: 69332
server_tid: 247
+ server_pid: 247
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25190,11 +26532,13 @@
client_ts: 25888119355
client_dur: 387727
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25888158284
server_dur: 330571
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25221,11 +26565,13 @@
client_ts: 25888835343
client_dur: 324156
client_tid: 665
+ client_pid: 641
server_process: "/system/bin/hwservicemanager"
server_thread: "hwservicemanage"
server_ts: 25888991319
server_dur: 112375
server_tid: 247
+ server_pid: 247
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25258,11 +26604,13 @@
client_ts: 24562258099
client_dur: 95711
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24562294551
server_dur: 25989
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25295,11 +26643,13 @@
client_ts: 24576142302
client_dur: 100932
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24576178251
server_dur: 35440
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25326,11 +26676,13 @@
client_ts: 24577928034
client_dur: 98898
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24577965065
server_dur: 33433
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25357,11 +26709,13 @@
client_ts: 24579825258
client_dur: 91999
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24579857006
server_dur: 32771
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25388,11 +26742,13 @@
client_ts: 24586203617
client_dur: 160861
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24586241455
server_dur: 29609
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25425,11 +26781,13 @@
client_ts: 24588923637
client_dur: 381582
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24588962975
server_dur: 29095
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25462,11 +26820,13 @@
client_ts: 24592040006
client_dur: 240562
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24592076186
server_dur: 28582
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25499,11 +26859,13 @@
client_ts: 24594213703
client_dur: 673648
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24594243436
server_dur: 22881
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25536,11 +26898,13 @@
client_ts: 24595958354
client_dur: 77980
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24595993807
server_dur: 22950
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25573,11 +26937,13 @@
client_ts: 24597520537
client_dur: 49553
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24597542932
server_dur: 16294
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25610,11 +26976,13 @@
client_ts: 24598897106
client_dur: 68689
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24598922372
server_dur: 18191
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25647,11 +27015,13 @@
client_ts: 24600413274
client_dur: 57521
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24600434769
server_dur: 13168
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25684,11 +27054,13 @@
client_ts: 24602399966
client_dur: 80715
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24602431540
server_dur: 23433
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25721,11 +27093,13 @@
client_ts: 24603839586
client_dur: 50942
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24603864064
server_dur: 11482
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25758,11 +27132,13 @@
client_ts: 24605137324
client_dur: 53391
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24605161847
server_dur: 16108
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25795,11 +27171,13 @@
client_ts: 24607833798
client_dur: 79225
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24607864767
server_dur: 25864
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25832,11 +27210,13 @@
client_ts: 24609098413
client_dur: 86504
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24609132077
server_dur: 29462
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25869,11 +27249,13 @@
client_ts: 24646418600
client_dur: 104600
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24646446859
server_dur: 25546
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25900,11 +27282,13 @@
client_ts: 24671385803
client_dur: 170289
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24671409853
server_dur: 37825
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25931,11 +27315,13 @@
client_ts: 24681379300
client_dur: 57187
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24681399705
server_dur: 21305
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25962,11 +27348,13 @@
client_ts: 24682251210
client_dur: 182307
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24682273023
server_dur: 20664
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -25993,11 +27381,13 @@
client_ts: 24683246275
client_dur: 207024
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24683267459
server_dur: 20968
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26024,11 +27414,13 @@
client_ts: 24685075466
client_dur: 189680
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24685097014
server_dur: 20394
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26055,11 +27447,13 @@
client_ts: 24687047835
client_dur: 52825
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24687065149
server_dur: 20404
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26086,11 +27480,13 @@
client_ts: 24690752961
client_dur: 1138197
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24690773594
server_dur: 20275
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26117,11 +27513,13 @@
client_ts: 24692956765
client_dur: 967152
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24692973830
server_dur: 19601
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26148,11 +27546,13 @@
client_ts: 24699086985
client_dur: 2761757
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24699105127
server_dur: 19717
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26191,11 +27591,13 @@
client_ts: 24704026795
client_dur: 151503
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24704048621
server_dur: 19875
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26222,11 +27624,13 @@
client_ts: 24707823403
client_dur: 418749
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24707844258
server_dur: 19420
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26253,11 +27657,13 @@
client_ts: 24715413797
client_dur: 55453
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24715432924
server_dur: 20515
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26284,11 +27690,13 @@
client_ts: 24718094584
client_dur: 396933
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24718112985
server_dur: 20123
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26315,11 +27723,13 @@
client_ts: 24720389105
client_dur: 56955
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24720410588
server_dur: 19497
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26346,11 +27756,13 @@
client_ts: 24722237372
client_dur: 57988
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24722254479
server_dur: 19636
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26377,11 +27789,13 @@
client_ts: 24724223102
client_dur: 52789
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24724240486
server_dur: 19628
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26408,11 +27822,13 @@
client_ts: 24727963525
client_dur: 54516
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24727983399
server_dur: 19277
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26439,11 +27855,13 @@
client_ts: 24729275294
client_dur: 69527
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24729308987
server_dur: 19817
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26470,11 +27888,13 @@
client_ts: 24730464621
client_dur: 56830
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24730486611
server_dur: 19083
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26501,11 +27921,13 @@
client_ts: 24731541792
client_dur: 59775
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24731563743
server_dur: 19533
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26532,11 +27954,13 @@
client_ts: 24732635124
client_dur: 62661
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24732657580
server_dur: 22874
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26563,11 +27987,13 @@
client_ts: 24733694931
client_dur: 58749
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24733718525
server_dur: 19626
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26594,11 +28020,13 @@
client_ts: 24734519268
client_dur: 56933
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24734541289
server_dur: 19505
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26625,11 +28053,13 @@
client_ts: 24735621739
client_dur: 59911
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24735644076
server_dur: 19698
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26656,11 +28086,13 @@
client_ts: 24737578050
client_dur: 70375
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24737599805
server_dur: 19338
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26687,11 +28119,13 @@
client_ts: 24738379435
client_dur: 59307
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24738401334
server_dur: 19247
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26718,11 +28152,13 @@
client_ts: 24739381820
client_dur: 59860
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24739404070
server_dur: 19274
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26749,11 +28185,13 @@
client_ts: 24740296188
client_dur: 60137
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24740318642
server_dur: 19217
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26780,11 +28218,13 @@
client_ts: 24741062753
client_dur: 60144
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24741084854
server_dur: 19235
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26811,11 +28251,13 @@
client_ts: 24742188157
client_dur: 62717
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24742210951
server_dur: 22644
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26842,11 +28284,13 @@
client_ts: 24743215720
client_dur: 57215
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24743238157
server_dur: 19299
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26873,11 +28317,13 @@
client_ts: 24744310059
client_dur: 62304
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24744332347
server_dur: 22570
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26904,11 +28350,13 @@
client_ts: 24745726015
client_dur: 42535
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24745741462
server_dur: 13274
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26935,11 +28383,13 @@
client_ts: 24746812940
client_dur: 62487
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24746836091
server_dur: 21679
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26966,11 +28416,13 @@
client_ts: 24747614390
client_dur: 60851
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24747636567
server_dur: 21322
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -26997,11 +28449,13 @@
client_ts: 24748641464
client_dur: 98796
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24748705431
server_dur: 19737
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27028,11 +28482,13 @@
client_ts: 24749789307
client_dur: 58174
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24749812809
server_dur: 19265
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27059,11 +28515,13 @@
client_ts: 24753793235
client_dur: 285781
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24753872138
server_dur: 21667
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27090,11 +28548,13 @@
client_ts: 24760573761
client_dur: 55871
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24760593814
server_dur: 19818
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27121,11 +28581,13 @@
client_ts: 24761811419
client_dur: 104650
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24761830688
server_dur: 19717
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27152,11 +28614,13 @@
client_ts: 24763891343
client_dur: 52306
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24763908905
server_dur: 19517
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27183,11 +28647,13 @@
client_ts: 24764906537
client_dur: 55552
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24764927197
server_dur: 19435
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27214,11 +28680,13 @@
client_ts: 24766255714
client_dur: 69186
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24766285051
server_dur: 22399
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27245,11 +28713,13 @@
client_ts: 24767227873
client_dur: 55587
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24767248556
server_dur: 19425
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27276,11 +28746,13 @@
client_ts: 24770081943
client_dur: 54467
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24770101200
server_dur: 19938
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27307,11 +28779,13 @@
client_ts: 24773596028
client_dur: 197569
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24773614039
server_dur: 28282
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27338,11 +28812,13 @@
client_ts: 24785387433
client_dur: 2028794
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24785409117
server_dur: 20078
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27369,11 +28845,13 @@
client_ts: 24788209976
client_dur: 153903
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24788233234
server_dur: 20622
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27400,11 +28878,13 @@
client_ts: 24789221986
client_dur: 57706
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24789245188
server_dur: 19214
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27431,11 +28911,13 @@
client_ts: 24790705709
client_dur: 65167
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24790730301
server_dur: 25107
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27462,11 +28944,13 @@
client_ts: 24791500958
client_dur: 57742
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24791523460
server_dur: 19471
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27493,11 +28977,13 @@
client_ts: 24792307538
client_dur: 58314
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24792330556
server_dur: 19368
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27524,11 +29010,13 @@
client_ts: 24793372795
client_dur: 57390
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24793395000
server_dur: 19464
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27555,11 +29043,13 @@
client_ts: 24794492101
client_dur: 54114
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24794511315
server_dur: 19523
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27586,11 +29076,13 @@
client_ts: 24795410099
client_dur: 54987
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24795430573
server_dur: 19258
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27617,11 +29109,13 @@
client_ts: 24796677839
client_dur: 55067
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24796698242
server_dur: 19086
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27648,11 +29142,13 @@
client_ts: 24797815386
client_dur: 53079
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24797833699
server_dur: 19213
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27679,11 +29175,13 @@
client_ts: 24799449503
client_dur: 56617
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24799470930
server_dur: 19513
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27710,11 +29208,13 @@
client_ts: 24805536696
client_dur: 49858
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24805554922
server_dur: 16943
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27741,11 +29241,13 @@
client_ts: 24808769073
client_dur: 53981
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24808788665
server_dur: 19040
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27772,11 +29274,13 @@
client_ts: 24821382491
client_dur: 48977
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24821399252
server_dur: 17308
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27803,11 +29307,13 @@
client_ts: 24825799132
client_dur: 58481
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24825818665
server_dur: 20241
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27834,11 +29340,13 @@
client_ts: 24836015985
client_dur: 60190
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24836036269
server_dur: 24240
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27865,11 +29373,13 @@
client_ts: 24838902949
client_dur: 155997
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24838939369
server_dur: 21040
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27902,11 +29412,13 @@
client_ts: 24842361861
client_dur: 70409
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24842390226
server_dur: 21512
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27939,11 +29451,13 @@
client_ts: 24849556375
client_dur: 183165
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24849690991
server_dur: 24294
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -27976,11 +29490,13 @@
client_ts: 24871639354
client_dur: 68462
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24871671014
server_dur: 22834
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28013,11 +29529,13 @@
client_ts: 24873845755
client_dur: 1096098
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24873871989
server_dur: 21071
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28044,11 +29562,13 @@
client_ts: 24877992364
client_dur: 187259
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24878014368
server_dur: 20564
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28081,11 +29601,13 @@
client_ts: 24881598747
client_dur: 82762
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24881620007
server_dur: 37794
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28118,11 +29640,13 @@
client_ts: 24882762008
client_dur: 343179
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24883063470
server_dur: 18976
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28155,11 +29679,13 @@
client_ts: 24884363797
client_dur: 138909
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24884469472
server_dur: 19017
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28192,11 +29718,13 @@
client_ts: 24886610735
client_dur: 64238
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24886632996
server_dur: 20186
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28229,11 +29757,13 @@
client_ts: 24888078440
client_dur: 422798
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24888463594
server_dur: 19313
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28266,11 +29796,13 @@
client_ts: 24891297979
client_dur: 58221
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24891321099
server_dur: 19916
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28303,11 +29835,13 @@
client_ts: 24893930550
client_dur: 54133
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24893950723
server_dur: 20568
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28340,11 +29874,13 @@
client_ts: 24896595580
client_dur: 67589
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24896624063
server_dur: 20320
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28377,11 +29913,13 @@
client_ts: 24903024474
client_dur: 206934
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24903154456
server_dur: 20235
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28414,11 +29952,13 @@
client_ts: 24915150978
client_dur: 62178
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24915179748
server_dur: 21871
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28451,11 +29991,13 @@
client_ts: 24921237169
client_dur: 1189989
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24921585066
server_dur: 22945
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28488,11 +30030,13 @@
client_ts: 24924342216
client_dur: 260104
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24924548644
server_dur: 20604
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28525,11 +30069,13 @@
client_ts: 24932907687
client_dur: 61496
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24932929991
server_dur: 21719
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28562,11 +30108,13 @@
client_ts: 24936245311
client_dur: 89729
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24936266250
server_dur: 20798
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28593,11 +30141,13 @@
client_ts: 24943311799
client_dur: 214359
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24943331082
server_dur: 20072
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28624,11 +30174,13 @@
client_ts: 24967426046
client_dur: 238772
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 24967447878
server_dur: 21398
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28655,11 +30207,13 @@
client_ts: 25003883218
client_dur: 324891
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25003925054
server_dur: 43609
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28686,11 +30240,13 @@
client_ts: 25025076994
client_dur: 190930
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25025118986
server_dur: 30435
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28723,11 +30279,13 @@
client_ts: 25034377812
client_dur: 271653
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25034403338
server_dur: 27240
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28754,11 +30312,13 @@
client_ts: 25036622369
client_dur: 268217
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25036650886
server_dur: 26015
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28785,11 +30345,13 @@
client_ts: 25048460597
client_dur: 56503
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25048480970
server_dur: 20752
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28816,11 +30378,13 @@
client_ts: 25056764479
client_dur: 56793
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25056784331
server_dur: 20103
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28847,11 +30411,13 @@
client_ts: 25073721612
client_dur: 55061
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25073740814
server_dur: 20447
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28878,11 +30444,13 @@
client_ts: 25110161805
client_dur: 81154
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25110196375
server_dur: 24505
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28915,11 +30483,13 @@
client_ts: 25118254173
client_dur: 89345
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25118275515
server_dur: 30281
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28946,11 +30516,13 @@
client_ts: 25126211905
client_dur: 156793
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25126252664
server_dur: 31152
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -28983,11 +30555,13 @@
client_ts: 25128591519
client_dur: 86261
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25128613762
server_dur: 22079
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29014,11 +30588,13 @@
client_ts: 25137455943
client_dur: 138560
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25137492801
server_dur: 24108
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29051,11 +30627,13 @@
client_ts: 25171098007
client_dur: 86786
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25171119721
server_dur: 24637
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29082,11 +30660,13 @@
client_ts: 25176666011
client_dur: 68313
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25176690933
server_dur: 22908
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29125,11 +30705,13 @@
client_ts: 25180015030
client_dur: 119578
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25180094139
server_dur: 21082
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29168,11 +30750,13 @@
client_ts: 25185495297
client_dur: 90240
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25185546375
server_dur: 20903
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29211,11 +30795,13 @@
client_ts: 25190169442
client_dur: 56523
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25190190035
server_dur: 19360
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29248,11 +30834,13 @@
client_ts: 25192159947
client_dur: 67609
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25192191721
server_dur: 19584
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29285,11 +30873,13 @@
client_ts: 25194833721
client_dur: 54386
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25194853231
server_dur: 19541
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29316,11 +30906,13 @@
client_ts: 25197865886
client_dur: 55290
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25197885904
server_dur: 19555
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29347,11 +30939,13 @@
client_ts: 25205510080
client_dur: 53971
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25205529822
server_dur: 19108
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29378,11 +30972,13 @@
client_ts: 25210682525
client_dur: 54427
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25210701854
server_dur: 19875
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29409,11 +31005,13 @@
client_ts: 25212773102
client_dur: 143598
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25212807375
server_dur: 20140
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29446,11 +31044,13 @@
client_ts: 25219095678
client_dur: 62570
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25219117631
server_dur: 20590
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29490,11 +31090,13 @@
client_ts: 25230101202
client_dur: 295436
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25230125660
server_dur: 202423
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29528,11 +31130,13 @@
client_ts: 25243511980
client_dur: 489650
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25243544499
server_dur: 438512
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -29590,11 +31194,13 @@
client_ts: 25244949065
client_dur: 33302645
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25244971300
server_dur: 33241468
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -29676,11 +31282,13 @@
client_ts: 25279371214
client_dur: 141670
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25279387389
server_dur: 110471
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29714,11 +31322,13 @@
client_ts: 25279567724
client_dur: 1117204
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25279592927
server_dur: 1062729
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -29776,11 +31386,13 @@
client_ts: 25280736368
client_dur: 173449
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25280756522
server_dur: 131586
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29814,11 +31426,13 @@
client_ts: 25280932813
client_dur: 166964
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25280946041
server_dur: 122533
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29852,11 +31466,13 @@
client_ts: 25281131360
client_dur: 127300
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25281145719
server_dur: 98609
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29890,11 +31506,13 @@
client_ts: 25281273755
client_dur: 152610
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25281315273
server_dur: 97815
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29928,11 +31546,13 @@
client_ts: 25281454812
client_dur: 120876
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25281470206
server_dur: 94381
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -29966,11 +31586,13 @@
client_ts: 25281590129
client_dur: 151723
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25281611020
server_dur: 119089
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30004,11 +31626,13 @@
client_ts: 25281756115
client_dur: 115379
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25281769371
server_dur: 91666
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30042,11 +31666,13 @@
client_ts: 25281884499
client_dur: 116250
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25281896268
server_dur: 93727
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30080,11 +31706,13 @@
client_ts: 25282021405
client_dur: 113709
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25282032972
server_dur: 91541
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30118,11 +31746,13 @@
client_ts: 25282147043
client_dur: 114363
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25282159024
server_dur: 91525
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30156,11 +31786,13 @@
client_ts: 25282273296
client_dur: 113496
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25282285050
server_dur: 91191
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30194,11 +31826,13 @@
client_ts: 25282398433
client_dur: 133314
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25282413336
server_dur: 107722
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30232,11 +31866,13 @@
client_ts: 25282543082
client_dur: 113069
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25282556151
server_dur: 89003
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30270,11 +31906,13 @@
client_ts: 25282667987
client_dur: 110166
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25282679437
server_dur: 87774
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30308,11 +31946,13 @@
client_ts: 25282789771
client_dur: 113837
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25282802242
server_dur: 90943
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30346,11 +31986,13 @@
client_ts: 25282914877
client_dur: 111627
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25282927602
server_dur: 88554
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30384,11 +32026,13 @@
client_ts: 25283038152
client_dur: 1992379
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_2"
server_ts: 25284866843
server_dur: 141149
server_tid: 548
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30421,11 +32065,13 @@
client_ts: 25374394471
client_dur: 2049689
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25374452290
server_dur: 56976
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30452,11 +32098,13 @@
client_ts: 25376513735
client_dur: 1298945
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25376552511
server_dur: 1229818
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -30513,11 +32161,13 @@
client_ts: 25380873939
client_dur: 94827
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25380918552
server_dur: 29189
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30544,11 +32194,13 @@
client_ts: 25382555538
client_dur: 499495
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25382942898
server_dur: 73464
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30581,11 +32233,13 @@
client_ts: 25383224119
client_dur: 475348
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25383318022
server_dur: 71453
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30618,11 +32272,13 @@
client_ts: 25384246889
client_dur: 2183818
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25386357038
server_dur: 45022
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30655,11 +32311,13 @@
client_ts: 25386462748
client_dur: 100360
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25386487821
server_dur: 60382
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30686,11 +32344,13 @@
client_ts: 25386597595
client_dur: 98608
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25386619074
server_dur: 61591
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30717,11 +32377,13 @@
client_ts: 25386719729
client_dur: 86786
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25386741757
server_dur: 49965
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30748,11 +32410,13 @@
client_ts: 25386829528
client_dur: 89755
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25386849083
server_dur: 55739
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30779,11 +32443,13 @@
client_ts: 25386948016
client_dur: 83210
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25386968208
server_dur: 48426
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30810,11 +32476,13 @@
client_ts: 25387051427
client_dur: 82153
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25387070661
server_dur: 48379
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30841,11 +32509,13 @@
client_ts: 25387162195
client_dur: 82295
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25387182559
server_dur: 47439
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30872,11 +32542,13 @@
client_ts: 25387268275
client_dur: 86930
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25387287442
server_dur: 52733
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30903,11 +32575,13 @@
client_ts: 25400532103
client_dur: 58804
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25400550889
server_dur: 23976
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30934,11 +32608,13 @@
client_ts: 25400815946
client_dur: 53189
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25400833837
server_dur: 20666
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30965,11 +32641,13 @@
client_ts: 25426768392
client_dur: 59432
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25426787956
server_dur: 24158
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -30996,11 +32674,13 @@
client_ts: 25428341210
client_dur: 87943
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25428360065
server_dur: 51321
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -31028,11 +32708,13 @@
client_ts: 25428597840
client_dur: 1897216
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_1"
server_ts: 25428614184
server_dur: 1721051
server_tid: 557
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -31108,11 +32790,13 @@
client_ts: 25430545529
client_dur: 5604165
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_1"
server_ts: 25430555701
server_dur: 5580114
server_tid: 557
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -31176,11 +32860,13 @@
client_ts: 25436197115
client_dur: 165295
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_2"
server_ts: 25436268304
server_dur: 84720
server_tid: 541
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -31214,11 +32900,13 @@
client_ts: 25436454693
client_dur: 101710
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_1"
server_ts: 25436467750
server_dur: 68620
server_tid: 557
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -31258,11 +32946,13 @@
client_ts: 25436579821
client_dur: 1131075
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_2"
server_ts: 25436605605
server_dur: 1092472
server_tid: 541
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -31296,11 +32986,13 @@
client_ts: 25437807385
client_dur: 35309
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_2"
server_ts: 25437821151
server_dur: 13284
server_tid: 541
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -31334,11 +33026,13 @@
client_ts: 25437906939
client_dur: 108314
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_1"
server_ts: 25437930754
server_dur: 65111
server_tid: 557
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -31384,11 +33078,13 @@
client_ts: 25438037598
client_dur: 1231074
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_1"
server_ts: 25438067211
server_dur: 1188167
server_tid: 557
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -31428,11 +33124,13 @@
client_ts: 25439303208
client_dur: 56463
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_1"
server_ts: 25439340083
server_dur: 11933
server_tid: 557
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -31466,11 +33164,13 @@
client_ts: 25439404915
client_dur: 28249
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_1"
server_ts: 25439417069
server_dur: 8812
server_tid: 557
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -31504,11 +33204,13 @@
client_ts: 25439834153
client_dur: 149238
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_1"
server_ts: 25439854310
server_dur: 63659
server_tid: 557
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -31548,11 +33250,13 @@
client_ts: 25440007897
client_dur: 617701
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25440026034
server_dur: 581007
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -31586,11 +33290,13 @@
client_ts: 25440650480
client_dur: 37954
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25440669130
server_dur: 11644
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -31624,11 +33330,13 @@
client_ts: 25440744629
client_dur: 130786
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25440759041
server_dur: 97590
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -31668,11 +33376,13 @@
client_ts: 25440898977
client_dur: 1131318
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_1"
server_ts: 25440930592
server_dur: 1086590
server_tid: 557
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -31718,11 +33428,13 @@
client_ts: 25442065948
client_dur: 37271
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_1"
server_ts: 25442083599
server_dur: 12197
server_tid: 557
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -31756,11 +33468,13 @@
client_ts: 25442154751
client_dur: 91298
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25442164438
server_dur: 64020
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -31800,11 +33514,13 @@
client_ts: 25442267983
client_dur: 969844
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25442291581
server_dur: 932552
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -31844,11 +33560,13 @@
client_ts: 25443270028
client_dur: 50947
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25443301118
server_dur: 11975
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -31882,11 +33600,13 @@
client_ts: 25443369306
client_dur: 97383
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25443387190
server_dur: 61382
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -31926,11 +33646,13 @@
client_ts: 25443488838
client_dur: 710384
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25443518308
server_dur: 668611
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -31976,11 +33698,13 @@
client_ts: 25444231572
client_dur: 52027
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25444264016
server_dur: 12085
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32014,11 +33738,13 @@
client_ts: 25444518761
client_dur: 104456
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25444539803
server_dur: 63755
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32058,11 +33784,13 @@
client_ts: 25444646123
client_dur: 413789
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25444674530
server_dur: 371297
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32096,11 +33824,13 @@
client_ts: 25445078459
client_dur: 37933
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25445097539
server_dur: 11521
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32134,11 +33864,13 @@
client_ts: 25445162965
client_dur: 98821
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25445176700
server_dur: 65755
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32178,11 +33910,13 @@
client_ts: 25445283998
client_dur: 1223250
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25445325570
server_dur: 1169074
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32228,11 +33962,13 @@
client_ts: 25446539928
client_dur: 55845
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25446574718
server_dur: 12523
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32266,11 +34002,13 @@
client_ts: 25446655842
client_dur: 102770
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25446673983
server_dur: 64748
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32310,11 +34048,13 @@
client_ts: 25446780771
client_dur: 484620
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25446802921
server_dur: 383705
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32354,11 +34094,13 @@
client_ts: 25447296204
client_dur: 32106
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25447307403
server_dur: 12025
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32392,11 +34134,13 @@
client_ts: 25447383428
client_dur: 99654
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25447399103
server_dur: 64249
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32436,11 +34180,13 @@
client_ts: 25447504358
client_dur: 1088603
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25447527457
server_dur: 1052788
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -32486,11 +34232,13 @@
client_ts: 25448618882
client_dur: 65160
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25448662606
server_dur: 12297
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32524,11 +34272,13 @@
client_ts: 25448732540
client_dur: 90622
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25448745055
server_dur: 61605
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32568,11 +34318,13 @@
client_ts: 25448844089
client_dur: 1341222
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25448878397
server_dur: 1294973
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32612,11 +34364,13 @@
client_ts: 25450214696
client_dur: 132324
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25450325232
server_dur: 12314
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32650,11 +34404,13 @@
client_ts: 25450401044
client_dur: 34066
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25450413421
server_dur: 8832
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32688,11 +34444,13 @@
client_ts: 25450477847
client_dur: 108090
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25450488460
server_dur: 82190
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32732,11 +34490,13 @@
client_ts: 25450607703
client_dur: 1259215
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25450647353
server_dur: 1203353
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32776,11 +34536,13 @@
client_ts: 25451902370
client_dur: 111453
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25451993380
server_dur: 11814
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32814,11 +34576,13 @@
client_ts: 25452994340
client_dur: 109726
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25453017159
server_dur: 64867
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32858,11 +34622,13 @@
client_ts: 25453126725
client_dur: 1046699
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25453215693
server_dur: 328275
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32896,11 +34662,13 @@
client_ts: 25454206920
client_dur: 37100
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25454216327
server_dur: 14099
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -32934,11 +34702,13 @@
client_ts: 25454305892
client_dur: 105614
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25454321058
server_dur: 71322
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -32978,11 +34748,13 @@
client_ts: 25454433615
client_dur: 1182599
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25454454326
server_dur: 1148464
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -33022,11 +34794,13 @@
client_ts: 25455648152
client_dur: 89055
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25455717688
server_dur: 10552
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33060,11 +34834,13 @@
client_ts: 25455783097
client_dur: 77504
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25455796471
server_dur: 53966
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33098,11 +34874,13 @@
client_ts: 25455870323
client_dur: 183133
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25455880236
server_dur: 164382
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33136,11 +34914,13 @@
client_ts: 25456454160
client_dur: 31893
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25456468473
server_dur: 7849
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33174,11 +34954,13 @@
client_ts: 25456548523
client_dur: 98167
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25456560742
server_dur: 75793
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -33218,11 +35000,13 @@
client_ts: 25456659359
client_dur: 202533
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25456689304
server_dur: 163129
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33256,11 +35040,13 @@
client_ts: 25456872988
client_dur: 29135
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/idmap2d"
server_thread: "binder:541_3"
server_ts: 25456888657
server_dur: 6402
server_tid: 1598
+ server_pid: 541
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33293,11 +35079,13 @@
client_ts: 25494548191
client_dur: 258095
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25494622231
server_dur: 150527
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33330,11 +35118,13 @@
client_ts: 25495244473
client_dur: 325048
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25495400405
server_dur: 128258
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33367,11 +35157,13 @@
client_ts: 25504141418
client_dur: 297361
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25504207270
server_dur: 133515
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33398,11 +35190,13 @@
client_ts: 25511329109
client_dur: 678596
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25511805543
server_dur: 136659
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33435,11 +35229,13 @@
client_ts: 25517948532
client_dur: 163240
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25518009843
server_dur: 44297
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33472,11 +35268,13 @@
client_ts: 25518739183
client_dur: 3265864
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25518779467
server_dur: 374561
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33509,11 +35307,13 @@
client_ts: 25523067296
client_dur: 1153803
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25523345752
server_dur: 24699
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33546,11 +35346,13 @@
client_ts: 25529407157
client_dur: 1243348
client_tid: 641
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.health-service.cuttlefish"
server_thread: "android.hardwar"
server_ts: 25529886580
server_dur: 502254
server_tid: 431
+ server_pid: 431
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -33589,11 +35391,13 @@
client_ts: 25530820205
client_dur: 1517480
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25530877699
server_dur: 79639
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33626,11 +35430,13 @@
client_ts: 25538312793
client_dur: 177283
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25538360355
server_dur: 73011
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33663,11 +35469,13 @@
client_ts: 25538521832
client_dur: 115418
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25538557132
server_dur: 51687
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33700,11 +35508,13 @@
client_ts: 25555649759
client_dur: 401986
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25555822535
server_dur: 166864
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33737,11 +35547,13 @@
client_ts: 25562439114
client_dur: 360669
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25562601598
server_dur: 147343
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33774,11 +35586,13 @@
client_ts: 25564138751
client_dur: 227016
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25564207677
server_dur: 112964
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33811,11 +35625,13 @@
client_ts: 25564950504
client_dur: 216354
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25565018623
server_dur: 104733
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33848,11 +35664,13 @@
client_ts: 25565861693
client_dur: 154693
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25565923809
server_dur: 44929
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33886,11 +35704,13 @@
client_ts: 25566098278
client_dur: 3268381
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25566134660
server_dur: 2297021
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33923,11 +35743,13 @@
client_ts: 25578643057
client_dur: 230121
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25578709142
server_dur: 126093
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33954,11 +35776,13 @@
client_ts: 25579716604
client_dur: 216367
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25579776806
server_dur: 121078
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -33985,11 +35809,13 @@
client_ts: 25584224256
client_dur: 249444
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25584297755
server_dur: 135137
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34016,11 +35842,13 @@
client_ts: 25585086651
client_dur: 284206
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25585152822
server_dur: 129855
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34047,11 +35875,13 @@
client_ts: 25587741520
client_dur: 249445
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25587810843
server_dur: 138515
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34078,11 +35908,13 @@
client_ts: 25588452300
client_dur: 243841
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25588512250
server_dur: 145542
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34109,11 +35941,13 @@
client_ts: 25607046968
client_dur: 141541
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25607085845
server_dur: 83802
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34140,11 +35974,13 @@
client_ts: 25626771532
client_dur: 407539
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25627067466
server_dur: 61702
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34177,11 +36013,13 @@
client_ts: 25627247935
client_dur: 118074
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25627290693
server_dur: 38186
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34208,11 +36046,13 @@
client_ts: 25627461473
client_dur: 244900
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25627519338
server_dur: 149891
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34239,11 +36079,13 @@
client_ts: 25632313567
client_dur: 258248
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25632388552
server_dur: 141000
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34270,11 +36112,13 @@
client_ts: 25637260298
client_dur: 196517
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25637328529
server_dur: 88341
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34301,11 +36145,13 @@
client_ts: 25656975183
client_dur: 72577
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25656999460
server_dur: 31187
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34332,11 +36178,13 @@
client_ts: 25657158859
client_dur: 49143
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25657175302
server_dur: 18337
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34363,11 +36211,13 @@
client_ts: 25659444951
client_dur: 67480
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25659467572
server_dur: 27682
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34394,11 +36244,13 @@
client_ts: 25710903029
client_dur: 196994
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25710975935
server_dur: 69286
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34431,11 +36283,13 @@
client_ts: 25779384485
client_dur: 6404465
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25779465833
server_dur: 115210
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34468,11 +36322,13 @@
client_ts: 25785903212
client_dur: 173175
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25785969981
server_dur: 74609
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34505,11 +36361,13 @@
client_ts: 25786187023
client_dur: 71969
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25786216656
server_dur: 16443
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34542,11 +36400,13 @@
client_ts: 25788338381
client_dur: 66978
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25788365130
server_dur: 26182
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34579,11 +36439,13 @@
client_ts: 25788426430
client_dur: 44938
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25788444575
server_dur: 12371
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34616,11 +36478,13 @@
client_ts: 25794664939
client_dur: 125489
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25794702859
server_dur: 70821
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34647,11 +36511,13 @@
client_ts: 25803399428
client_dur: 125121
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25803446233
server_dur: 61602
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34684,11 +36550,13 @@
client_ts: 25805561097
client_dur: 258904
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25805581639
server_dur: 24195
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34715,11 +36583,13 @@
client_ts: 25806638177
client_dur: 383567
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25806656214
server_dur: 348438
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34746,11 +36616,13 @@
client_ts: 25807042562
client_dur: 45260
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25807056567
server_dur: 14991
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34777,11 +36649,13 @@
client_ts: 25807129635
client_dur: 626529
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25807318058
server_dur: 335442
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "D"
@@ -34832,11 +36706,13 @@
client_ts: 25807794682
client_dur: 197460
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25807808849
server_dur: 31598
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34869,11 +36745,13 @@
client_ts: 25808041191
client_dur: 152874
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808112547
server_dur: 38477
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34906,11 +36784,13 @@
client_ts: 25808300543
client_dur: 216110
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808488934
server_dur: 5816
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34943,11 +36823,13 @@
client_ts: 25808536171
client_dur: 29720
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808549475
server_dur: 6142
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -34980,11 +36862,13 @@
client_ts: 25808580143
client_dur: 23193
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808589636
server_dur: 4653
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35017,11 +36901,13 @@
client_ts: 25808614611
client_dur: 24483
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808626104
server_dur: 4244
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35054,11 +36940,13 @@
client_ts: 25808649459
client_dur: 19535
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808656163
server_dur: 4039
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35091,11 +36979,13 @@
client_ts: 25808679113
client_dur: 22778
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808688986
server_dur: 3889
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35128,11 +37018,13 @@
client_ts: 25808712146
client_dur: 21102
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808720606
server_dur: 3664
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35165,11 +37057,13 @@
client_ts: 25808743343
client_dur: 49190
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808773138
server_dur: 4014
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35202,11 +37096,13 @@
client_ts: 25808803408
client_dur: 47244
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808832840
server_dur: 3744
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35239,11 +37135,13 @@
client_ts: 25808861280
client_dur: 23141
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808871693
server_dur: 4083
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35276,11 +37174,13 @@
client_ts: 25808894304
client_dur: 22212
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808903846
server_dur: 4193
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35313,11 +37213,13 @@
client_ts: 25808927915
client_dur: 23489
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808938201
server_dur: 4441
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35350,11 +37252,13 @@
client_ts: 25808963769
client_dur: 21106
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25808972274
server_dur: 4301
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35387,11 +37291,13 @@
client_ts: 25808996827
client_dur: 22150
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809006677
server_dur: 3852
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35424,11 +37330,13 @@
client_ts: 25809029487
client_dur: 30653
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809048418
server_dur: 3146
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35461,11 +37369,13 @@
client_ts: 25809070927
client_dur: 105314
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809156958
server_dur: 4090
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35498,11 +37408,13 @@
client_ts: 25809187458
client_dur: 21199
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809196575
server_dur: 3729
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35535,11 +37447,13 @@
client_ts: 25809219112
client_dur: 20851
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809227683
server_dur: 3856
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35572,11 +37486,13 @@
client_ts: 25809250949
client_dur: 271118
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809502291
server_dur: 4522
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35609,11 +37525,13 @@
client_ts: 25809543172
client_dur: 29191
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809555589
server_dur: 4714
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35646,11 +37564,13 @@
client_ts: 25809583743
client_dur: 23569
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809592470
server_dur: 3948
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35683,11 +37603,13 @@
client_ts: 25809618388
client_dur: 38876
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809637992
server_dur: 8798
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35720,11 +37642,13 @@
client_ts: 25809757746
client_dur: 171172
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809770125
server_dur: 89637
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -35763,11 +37687,13 @@
client_ts: 25809948987
client_dur: 120274
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25809967298
server_dur: 27536
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35800,11 +37726,13 @@
client_ts: 25810106019
client_dur: 110073
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25810132739
server_dur: 5193
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35837,11 +37765,13 @@
client_ts: 25810239347
client_dur: 148792
client_tid: 641
+ client_pid: 641
server_process: "/apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example"
server_thread: "android.hardwar"
server_ts: 25810364813
server_dur: 3865
server_tid: 481
+ server_pid: 481
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35874,11 +37804,13 @@
client_ts: 25810497904
client_dur: 126359
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25810531969
server_dur: 73542
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35905,11 +37837,13 @@
client_ts: 25810646589
client_dur: 91503
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25810669576
server_dur: 52662
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35936,11 +37870,13 @@
client_ts: 25810948647
client_dur: 113503
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25810980358
server_dur: 64314
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35967,11 +37903,13 @@
client_ts: 25811246975
client_dur: 366342
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25811269261
server_dur: 324989
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -35998,11 +37936,13 @@
client_ts: 25811641918
client_dur: 83600
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25811659549
server_dur: 47010
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -36035,11 +37975,13 @@
client_ts: 25811827364
client_dur: 105911
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25811855742
server_dur: 60946
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36066,11 +38008,13 @@
client_ts: 25814468030
client_dur: 128573
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25814502303
server_dur: 75807
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36097,11 +38041,13 @@
client_ts: 25824457100
client_dur: 243653
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25824484172
server_dur: 202360
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -36134,11 +38080,13 @@
client_ts: 25826929585
client_dur: 134380
client_tid: 1618
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25826953314
server_dur: 57893
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36171,11 +38119,13 @@
client_ts: 25827095345
client_dur: 59551
client_tid: 1618
+ client_pid: 641
server_process: "/apex/com.android.os.statsd/bin/statsd"
server_thread: "binder:415_3"
server_ts: 25827112546
server_dur: 28045
server_tid: 422
+ server_pid: 415
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36208,11 +38158,13 @@
client_ts: 25828178041
client_dur: 75912
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25828192051
server_dur: 26713
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36245,11 +38197,13 @@
client_ts: 25828289955
client_dur: 48095
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25828303964
server_dur: 23818
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36282,11 +38236,13 @@
client_ts: 25833585425
client_dur: 213739
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25833674904
server_dur: 59579
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36319,11 +38275,13 @@
client_ts: 25834911169
client_dur: 66864
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25834940005
server_dur: 22905
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36356,11 +38314,13 @@
client_ts: 25835009103
client_dur: 41035
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25835029405
server_dur: 9917
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36393,11 +38353,13 @@
client_ts: 25835084036
client_dur: 39828
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25835102285
server_dur: 11104
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36430,11 +38392,13 @@
client_ts: 25835225817
client_dur: 39668
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25835244300
server_dur: 10401
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36467,11 +38431,13 @@
client_ts: 25835491757
client_dur: 94706
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25835523199
server_dur: 50044
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36504,11 +38470,13 @@
client_ts: 25838116144
client_dur: 101371
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25838145038
server_dur: 57786
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36535,11 +38503,13 @@
client_ts: 25854689410
client_dur: 72379
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25854716713
server_dur: 29735
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36572,11 +38542,13 @@
client_ts: 25854776152
client_dur: 84994
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25854792697
server_dur: 55053
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36609,11 +38581,13 @@
client_ts: 25856165265
client_dur: 41372
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25856179451
server_dur: 11065
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36646,11 +38620,13 @@
client_ts: 25859386674
client_dur: 62804
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25859406671
server_dur: 23198
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36677,11 +38653,13 @@
client_ts: 25860119896
client_dur: 89982
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25860140536
server_dur: 54911
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36708,11 +38686,13 @@
client_ts: 25861940989
client_dur: 112198
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25861960190
server_dur: 69698
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36745,11 +38725,13 @@
client_ts: 25862411224
client_dur: 72918
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25862426577
server_dur: 43364
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36782,11 +38764,13 @@
client_ts: 25862572364
client_dur: 43335
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25862583679
server_dur: 21214
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36819,11 +38803,13 @@
client_ts: 25862644016
client_dur: 35084
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25862653442
server_dur: 16522
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36856,11 +38842,13 @@
client_ts: 25862703240
client_dur: 43193
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25862712076
server_dur: 25328
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36893,11 +38881,13 @@
client_ts: 25863309305
client_dur: 56073
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25863321886
server_dur: 30965
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36930,11 +38920,13 @@
client_ts: 25863414967
client_dur: 48999
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25863426312
server_dur: 27403
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -36967,11 +38959,13 @@
client_ts: 25864046858
client_dur: 61808
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864062070
server_dur: 32956
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37004,11 +38998,13 @@
client_ts: 25864143436
client_dur: 51337
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864153386
server_dur: 30980
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37041,11 +39037,13 @@
client_ts: 25864216828
client_dur: 37990
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864226073
server_dur: 19004
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37078,11 +39076,13 @@
client_ts: 25864279759
client_dur: 37961
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864288819
server_dur: 19366
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37115,11 +39115,13 @@
client_ts: 25864345023
client_dur: 59115
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864354391
server_dur: 17778
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37152,11 +39154,13 @@
client_ts: 25864449726
client_dur: 51629
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864460717
server_dur: 26406
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37189,11 +39193,13 @@
client_ts: 25864530175
client_dur: 40230
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864539824
server_dur: 19580
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37226,11 +39232,13 @@
client_ts: 25864603443
client_dur: 64958
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864612742
server_dur: 44603
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37263,11 +39271,13 @@
client_ts: 25864687472
client_dur: 38679
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864696221
server_dur: 19520
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37300,11 +39310,13 @@
client_ts: 25864748376
client_dur: 41144
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864757238
server_dur: 21548
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37337,11 +39349,13 @@
client_ts: 25864814870
client_dur: 37926
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864824299
server_dur: 17299
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37374,11 +39388,13 @@
client_ts: 25864878443
client_dur: 41432
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864887850
server_dur: 21263
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37411,11 +39427,13 @@
client_ts: 25864943354
client_dur: 46446
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25864953070
server_dur: 26259
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37448,11 +39466,13 @@
client_ts: 25865010220
client_dur: 42768
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25865018943
server_dur: 22857
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37485,11 +39505,13 @@
client_ts: 25865078882
client_dur: 42845
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25865088374
server_dur: 22790
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37522,11 +39544,13 @@
client_ts: 25865143746
client_dur: 43541
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25865152587
server_dur: 24329
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37559,11 +39583,13 @@
client_ts: 25865208871
client_dur: 37989
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25865217954
server_dur: 18361
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37596,11 +39622,13 @@
client_ts: 25865269510
client_dur: 180816
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25865278803
server_dur: 44675
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -37639,11 +39667,13 @@
client_ts: 25865509380
client_dur: 1204393
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25866655580
server_dur: 37015
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37676,11 +39706,13 @@
client_ts: 25866765533
client_dur: 52077
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25866778140
server_dur: 25314
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37713,11 +39745,13 @@
client_ts: 25866847306
client_dur: 36125
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25866856611
server_dur: 17873
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37750,11 +39784,13 @@
client_ts: 25866907704
client_dur: 31809
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25866916674
server_dur: 14121
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37787,11 +39823,13 @@
client_ts: 25866963934
client_dur: 42576
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25866972903
server_dur: 18950
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37824,11 +39862,13 @@
client_ts: 25867031282
client_dur: 35871
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867040421
server_dur: 17984
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37861,11 +39901,13 @@
client_ts: 25867092641
client_dur: 34611
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867101335
server_dur: 17329
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37898,11 +39940,13 @@
client_ts: 25867155069
client_dur: 43809
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867163773
server_dur: 26243
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37935,11 +39979,13 @@
client_ts: 25867229729
client_dur: 32631
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867238857
server_dur: 14033
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -37972,11 +40018,13 @@
client_ts: 25867283252
client_dur: 40731
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867292366
server_dur: 21993
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38009,11 +40057,13 @@
client_ts: 25867343753
client_dur: 34724
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867353084
server_dur: 16650
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38046,11 +40096,13 @@
client_ts: 25867401523
client_dur: 50745
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867410223
server_dur: 32741
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38083,11 +40135,13 @@
client_ts: 25867475251
client_dur: 46815
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867485001
server_dur: 26611
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38120,11 +40174,13 @@
client_ts: 25867547843
client_dur: 36696
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867557467
server_dur: 18125
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38157,11 +40213,13 @@
client_ts: 25867605981
client_dur: 37415
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867614819
server_dur: 19663
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38194,11 +40252,13 @@
client_ts: 25867663292
client_dur: 35879
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867672122
server_dur: 17373
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38231,11 +40291,13 @@
client_ts: 25867751966
client_dur: 40848
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867761875
server_dur: 19072
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38269,11 +40331,13 @@
client_ts: 25867845030
client_dur: 180504
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25867860282
server_dur: 154468
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "R"
@@ -38318,11 +40382,13 @@
client_ts: 25872260669
client_dur: 83399
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25872278450
server_dur: 47096
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38355,11 +40421,13 @@
client_ts: 25885439966
client_dur: 1549817
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25886054638
server_dur: 24145
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38392,11 +40460,13 @@
client_ts: 25885831452
client_dur: 1452935
client_tid: 1623
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25886206332
server_dur: 305512
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38429,11 +40499,13 @@
client_ts: 25887309449
client_dur: 115655
client_tid: 1623
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25887326271
server_dur: 18512
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38460,11 +40532,13 @@
client_ts: 25887452954
client_dur: 283867
client_tid: 1623
+ client_pid: 641
server_process: "/vendor/bin/hw/android.hardware.input.processor-service.example"
server_thread: "android.hardwar"
server_ts: 25887467255
server_dur: 38055
server_tid: 447
+ server_pid: 447
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38491,11 +40565,13 @@
client_ts: 25892252212
client_dur: 2274293
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25894481596
server_dur: 27702
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38528,11 +40604,13 @@
client_ts: 25921269728
client_dur: 400263
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25921599983
server_dur: 52448
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38565,11 +40643,13 @@
client_ts: 25921747025
client_dur: 209278
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25921878602
server_dur: 66173
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38602,11 +40682,13 @@
client_ts: 25922308759
client_dur: 230930
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25922366800
server_dur: 58914
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38639,11 +40721,13 @@
client_ts: 25926152660
client_dur: 106426
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25926184604
server_dur: 59798
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38676,11 +40760,13 @@
client_ts: 25935520343
client_dur: 106898
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25935553945
server_dur: 59988
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38713,11 +40799,13 @@
client_ts: 25936096478
client_dur: 38431
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25936114070
server_dur: 13878
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38750,11 +40838,13 @@
client_ts: 25936154115
client_dur: 304852
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25936427202
server_dur: 13388
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38787,11 +40877,13 @@
client_ts: 25939273894
client_dur: 44659
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25939290557
server_dur: 19990
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38824,11 +40916,13 @@
client_ts: 25939575552
client_dur: 81712
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25939602201
server_dur: 44933
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38861,11 +40955,13 @@
client_ts: 25944988176
client_dur: 71994
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25945018540
server_dur: 25217
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38898,11 +40994,13 @@
client_ts: 25948938076
client_dur: 82091
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25948980882
server_dur: 27091
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38935,11 +41033,13 @@
client_ts: 25951851055
client_dur: 445134
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_3"
server_ts: 25951902501
server_dur: 183967
server_tid: 1575
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -38972,11 +41072,13 @@
client_ts: 25952609949
client_dur: 44997
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_2"
server_ts: 25952623297
server_dur: 18258
server_tid: 522
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39003,11 +41105,13 @@
client_ts: 25954386897
client_dur: 107947
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/surfaceflinger"
server_thread: "binder:496_3"
server_ts: 25954404617
server_dur: 18018
server_tid: 1575
+ server_pid: 496
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39040,11 +41144,13 @@
client_ts: 25955417145
client_dur: 248980
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25955442657
server_dur: 23870
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39078,11 +41184,13 @@
client_ts: 25955702503
client_dur: 1028567
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25955716400
server_dur: 923564
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39109,11 +41217,13 @@
client_ts: 25957071212
client_dur: 244964
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25957109467
server_dur: 68828
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39146,11 +41256,13 @@
client_ts: 25957345364
client_dur: 86035
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25957361868
server_dur: 39522
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39183,11 +41295,13 @@
client_ts: 25957477722
client_dur: 38342
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25957490997
server_dur: 14607
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39220,11 +41334,13 @@
client_ts: 25957561902
client_dur: 115285
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/vold"
server_thread: "binder:255_2"
server_ts: 25957584457
server_dur: 69879
server_tid: 255
+ server_pid: 255
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39257,11 +41373,13 @@
client_ts: 25957701552
client_dur: 31673
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/vold"
server_thread: "binder:255_2"
server_ts: 25957712540
server_dur: 11337
server_tid: 255
+ server_pid: 255
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39294,11 +41412,13 @@
client_ts: 25957917714
client_dur: 81359
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25957965656
server_dur: 19953
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39331,11 +41451,13 @@
client_ts: 25958179475
client_dur: 57952
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25958197817
server_dur: 12909
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39368,11 +41490,13 @@
client_ts: 25958259037
client_dur: 37816
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25958272198
server_dur: 12201
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39406,11 +41530,13 @@
client_ts: 25958323889
client_dur: 934386
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25958335597
server_dur: 816593
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39438,11 +41564,13 @@
client_ts: 25959279820
client_dur: 780373
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/installd"
server_thread: "binder:548_1"
server_ts: 25959289960
server_dur: 697719
server_tid: 565
+ server_pid: 548
thread_states {
thread_state_type: "binder_reply"
thread_state: "R+"
@@ -39475,11 +41603,13 @@
client_ts: 25960212392
client_dur: 138312
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25960246748
server_dur: 59922
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39512,11 +41642,13 @@
client_ts: 25960703658
client_dur: 185272
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25960733334
server_dur: 55452
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
@@ -39549,11 +41681,13 @@
client_ts: 25964272455
client_dur: 108953
client_tid: 641
+ client_pid: 641
server_process: "/system/bin/servicemanager"
server_thread: "servicemanager"
server_ts: 25964304630
server_dur: 66130
server_tid: 243
+ server_pid: 243
thread_states {
thread_state_type: "binder_reply"
thread_state: "Running"
diff --git a/test/trace_processor/diff_tests/android/android_blocking_calls_cuj_metric.out b/test/trace_processor/diff_tests/android/android_blocking_calls_cuj_metric.out
index aa63194..d75d44d 100644
--- a/test/trace_processor/diff_tests/android/android_blocking_calls_cuj_metric.out
+++ b/test/trace_processor/diff_tests/android/android_blocking_calls_cuj_metric.out
@@ -5,6 +5,7 @@
process {
name: "com.android.systemui"
uid: 10001
+ pid: 1000
}
ts: 2000000
dur: 15000000
@@ -22,6 +23,7 @@
process {
name: "com.google.android.apps.nexuslauncher"
uid: 10002
+ pid: 2000
}
ts: 2000000
dur: 15000000
@@ -39,6 +41,7 @@
process {
name: "com.google.android.third.process"
uid: 10003
+ pid: 3000
}
ts: 2000000
dur: 150000000
@@ -147,6 +150,7 @@
process {
name: "com.android.systemui"
uid: 10001
+ pid: 1000
}
ts: 20000000
dur: 10000000
@@ -164,6 +168,7 @@
process {
name: "com.android.systemui"
uid: 10001
+ pid: 1000
}
ts: 22000000
dur: 10000000
@@ -175,4 +180,29 @@
min_dur_ms: 10
}
}
+ cuj {
+ id: 6
+ name: "WITH_NAMED_BINDER_TRANSACTION"
+ process {
+ name: "com.android.systemui"
+ uid: 10001
+ pid: 1000
+ }
+ ts: 40000000
+ dur: 10000000
+ blocking_calls {
+ name: "AIDL::java::IWindowManager::hasNavigationBar::server"
+ cnt: 1
+ total_dur_ms: 10
+ max_dur_ms: 10
+ min_dur_ms: 10
+ }
+ blocking_calls {
+ name: "binder transaction"
+ cnt: 1
+ total_dur_ms: 10
+ max_dur_ms: 10
+ min_dur_ms: 10
+ }
+ }
}
diff --git a/test/trace_processor/diff_tests/android/android_blocking_calls_cuj_metric.py b/test/trace_processor/diff_tests/android/android_blocking_calls_cuj_metric.py
index 7573b76..1039e47 100755
--- a/test/trace_processor/diff_tests/android/android_blocking_calls_cuj_metric.py
+++ b/test/trace_processor/diff_tests/android/android_blocking_calls_cuj_metric.py
@@ -45,6 +45,19 @@
trace.add_atrace_async_end(ts=ts_end, tid=pid, pid=pid, buf=buf)
+def add_binder_transaction(trace, tx_pid, rx_pid, start_ts, end_ts):
+ trace.add_binder_transaction(
+ transaction_id=tx_pid,
+ ts_start=start_ts,
+ ts_end=end_ts,
+ tid=tx_pid,
+ pid=tx_pid,
+ reply_id=rx_pid,
+ reply_ts_start=start_ts,
+ reply_ts_end=end_ts,
+ reply_tid=rx_pid,
+ reply_pid=rx_pid)
+
# Adds a set of predefined blocking calls in places near the cuj boundaries to
# verify that only the portion inside the cuj is counted in the metric.
def add_cuj_with_blocking_calls(trace, cuj_name, pid):
@@ -148,6 +161,31 @@
pid=pid)
+def add_cuj_with_named_binder_transaction(pid, rx_pid):
+ cuj_begin = 40_000_000
+ cuj_end = 50_000_000
+
+ add_async_trace(
+ trace,
+ ts=cuj_begin,
+ ts_end=cuj_end,
+ buf="L<WITH_NAMED_BINDER_TRANSACTION>",
+ pid=pid)
+
+ add_binder_transaction(
+ trace, tx_pid=pid, rx_pid=rx_pid, start_ts=cuj_begin, end_ts=cuj_end)
+
+ # Slice inside the binder reply, to give a name to the binder call.
+ # The named binder slice introduced should be the length of the entire
+ # transaction even if the "name" slice only covers some of the binder reply.
+ add_main_thread_atrace(
+ trace,
+ ts=cuj_begin + 1_000_000,
+ ts_end=cuj_end - 1_000_000,
+ buf="AIDL::java::IWindowManager::hasNavigationBar::server",
+ pid=rx_pid)
+
+
def add_process(trace, package_name, uid, pid):
trace.add_package_list(ts=0, name=package_name, uid=uid, version_code=1)
trace.add_process(
@@ -180,6 +218,8 @@
add_overlapping_cujs_with_blocking_calls(trace, pid=SYSUI_PID,
start_ts=20_000_000)
+add_cuj_with_named_binder_transaction(pid=SYSUI_PID, rx_pid=LAUNCHER_PID)
+
# Note that J<*> events are not tested here.
# See test_android_blocking_calls_on_jank_cujs.
sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/diff_tests/android/android_blocking_calls_on_jank_cuj_metric.out b/test/trace_processor/diff_tests/android/android_blocking_calls_on_jank_cuj_metric.out
index 68b3c9f..89d7c63 100644
--- a/test/trace_processor/diff_tests/android/android_blocking_calls_on_jank_cuj_metric.out
+++ b/test/trace_processor/diff_tests/android/android_blocking_calls_on_jank_cuj_metric.out
@@ -15,6 +15,7 @@
apk_version_code: 1
debuggable: false
}
+ pid: 1000
}
ts: 0
dur: 115000000
@@ -42,6 +43,7 @@
apk_version_code: 1
debuggable: false
}
+ pid: 1000
}
ts: 0
dur: 802000000
diff --git a/test/trace_processor/diff_tests/android/android_monitor_contention.out b/test/trace_processor/diff_tests/android/android_monitor_contention.out
index 02a6412..163815d 100644
--- a/test/trace_processor/diff_tests/android/android_monitor_contention.out
+++ b/test/trace_processor/diff_tests/android/android_monitor_contention.out
@@ -12,7 +12,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "PackageManager"
+ blocked_thread_tid: 693
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -39,7 +42,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -66,7 +72,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -93,7 +102,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "batterystats-ha"
+ blocked_thread_tid: 676
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -120,7 +132,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "binder:642_12"
+ blocked_thread_tid: 2720
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
binder_reply_ts: 1737055785896
@@ -154,7 +169,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "StorageUserConn"
+ blocked_thread_tid: 1759
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -171,7 +189,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "StorageUserConn"
+ blocked_thread_tid: 1759
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -208,7 +229,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -225,7 +249,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -242,7 +269,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -259,7 +289,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -276,7 +309,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -293,7 +329,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -310,7 +349,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -327,7 +369,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -344,7 +389,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -361,7 +409,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -378,7 +429,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -395,7 +449,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -412,7 +469,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -429,7 +489,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -446,7 +509,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -463,7 +529,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -480,7 +549,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -497,7 +569,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -514,7 +589,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -531,7 +609,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -548,7 +629,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -565,7 +649,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -582,7 +669,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -599,7 +689,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -616,7 +709,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -633,7 +729,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -650,7 +749,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -667,7 +769,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -684,7 +789,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -701,7 +809,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -718,7 +829,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -735,7 +849,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -752,7 +869,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -769,7 +889,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -786,7 +909,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -803,7 +929,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -820,7 +949,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -837,7 +969,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -854,7 +989,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -871,7 +1009,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -888,7 +1029,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -905,7 +1049,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -922,7 +1069,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -939,7 +1089,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -956,7 +1109,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -973,7 +1129,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -990,7 +1149,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1007,7 +1169,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1024,7 +1189,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1041,7 +1209,10 @@
waiter_count: 1
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.display"
+ blocked_thread_tid: 663
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1063,7 +1234,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1090,7 +1264,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1117,7 +1294,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1144,7 +1324,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "binder:642_11"
+ blocked_thread_tid: 2505
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1182,7 +1365,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "binder:642_12"
+ blocked_thread_tid: 2720
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1210,7 +1396,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "binder:642_12"
+ blocked_thread_tid: 2720
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1237,7 +1426,10 @@
waiter_count: 1
blocking_thread_name: "binder:642_12"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -1269,7 +1461,10 @@
waiter_count: 2
blocking_thread_name: "binder:642_12"
blocked_thread_name: "binder:642_2"
+ blocked_thread_tid: 658
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1291,7 +1486,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1308,7 +1506,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1325,7 +1526,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1342,7 +1546,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1359,7 +1566,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1376,7 +1586,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1393,7 +1606,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1410,7 +1626,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1427,7 +1646,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1444,7 +1666,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1461,7 +1686,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1478,7 +1706,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1495,7 +1726,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1512,7 +1746,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1529,7 +1766,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1546,7 +1786,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1563,7 +1806,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1580,7 +1826,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_12"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2720
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -1597,7 +1846,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1624,7 +1876,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1651,7 +1906,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1678,7 +1936,10 @@
waiter_count: 0
blocking_thread_name: "batterystats-handler"
blocked_thread_name: "binder:642_11"
+ blocked_thread_tid: 2505
+ blocking_thread_tid: 676
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1710,7 +1971,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1737,7 +2001,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1764,7 +2031,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1791,7 +2061,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1818,7 +2091,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1845,7 +2121,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1872,7 +2151,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1899,7 +2181,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1926,7 +2211,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1953,7 +2241,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -1980,7 +2271,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -2007,7 +2301,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -2034,7 +2331,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -2061,7 +2361,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -2088,7 +2391,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -2115,7 +2421,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -2142,7 +2451,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -2169,7 +2481,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_11"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 2505
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -2196,7 +2511,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "PowerManagerSer"
+ blocked_thread_tid: 687
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2223,7 +2541,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "PowerManagerSer"
+ blocked_thread_tid: 687
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2245,7 +2566,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "binder:642_2"
+ blocked_thread_tid: 658
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
binder_reply_ts: 1737145697570
@@ -2274,7 +2598,10 @@
waiter_count: 0
blocking_thread_name: "Thread-45"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 3486
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -2301,7 +2628,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "batterystats-ha"
+ blocked_thread_tid: 676
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2328,7 +2658,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "batterystats-ha"
+ blocked_thread_tid: 676
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2355,7 +2688,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "PowerManagerSer"
+ blocked_thread_tid: 687
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2382,7 +2718,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "PowerManagerSer"
+ blocked_thread_tid: 687
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2410,7 +2749,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "binder:642_14"
+ blocked_thread_tid: 3485
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -2442,7 +2784,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -2479,7 +2824,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2496,7 +2844,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2513,7 +2864,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2530,7 +2884,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "binder:642_11"
+ blocked_thread_tid: 2505
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
binder_reply_ts: 1737164232343
@@ -2549,7 +2906,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2566,7 +2926,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2583,7 +2946,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2600,7 +2966,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2617,7 +2986,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2634,7 +3006,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2651,7 +3026,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2668,7 +3046,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2685,7 +3066,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2702,7 +3086,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2719,7 +3106,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2736,7 +3126,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2753,7 +3146,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2770,7 +3166,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2787,7 +3186,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2804,7 +3206,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2821,7 +3226,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2838,7 +3246,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -2855,7 +3266,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "batterystats-ha"
+ blocked_thread_tid: 676
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2882,7 +3296,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2909,7 +3326,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2936,7 +3356,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2963,7 +3386,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -2990,7 +3416,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -3017,7 +3446,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -3044,7 +3476,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -3071,7 +3506,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -3098,7 +3536,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -3125,7 +3566,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -3152,7 +3596,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -3179,7 +3626,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -3206,7 +3656,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3233,7 +3686,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3260,7 +3716,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3287,7 +3746,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "binder:642_11"
+ blocked_thread_tid: 2505
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
binder_reply_ts: 1737183173575
@@ -3316,7 +3778,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "binder:642_14"
+ blocked_thread_tid: 3485
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3343,7 +3808,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3370,7 +3838,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3397,7 +3868,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3424,7 +3898,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3451,7 +3928,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3478,7 +3958,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3505,7 +3988,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3532,7 +4018,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3559,7 +4048,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3586,7 +4078,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3613,7 +4108,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3640,7 +4138,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3667,7 +4168,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3694,7 +4198,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3721,7 +4228,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3748,7 +4258,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3775,7 +4288,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3802,7 +4318,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_14"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 3485
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3829,7 +4348,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3856,7 +4378,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3883,7 +4408,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3910,7 +4438,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "binder:642_12"
+ blocked_thread_tid: 2720
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3947,7 +4478,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -3964,7 +4498,10 @@
waiter_count: 1
blocking_thread_name: "binder:642_E"
blocked_thread_name: "binder:642_2"
+ blocked_thread_tid: 658
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -3986,7 +4523,10 @@
waiter_count: 2
blocking_thread_name: "binder:642_E"
blocked_thread_name: "binder:642_A"
+ blocked_thread_tid: 1675
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4008,7 +4548,10 @@
waiter_count: 3
blocking_thread_name: "binder:642_E"
blocked_thread_name: "binder:642_8"
+ blocked_thread_tid: 1548
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4030,7 +4573,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_F"
blocked_thread_name: "binder:642_1"
+ blocked_thread_tid: 657
+ blocking_thread_tid: 2029
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4062,7 +4608,10 @@
waiter_count: 4
blocking_thread_name: "binder:642_E"
blocked_thread_name: "binder:642_13"
+ blocked_thread_tid: 2721
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4084,7 +4633,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4101,7 +4653,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4118,7 +4673,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4135,7 +4693,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4152,7 +4713,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4169,7 +4733,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4186,7 +4753,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4203,7 +4773,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4220,7 +4793,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4237,7 +4813,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4254,7 +4833,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4271,7 +4853,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4288,7 +4873,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4305,7 +4893,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4322,7 +4913,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4339,7 +4933,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -4356,7 +4953,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "binder:642_12"
+ blocked_thread_tid: 2720
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4383,7 +4983,10 @@
waiter_count: 0
blocking_thread_name: "android.ui"
blocked_thread_name: "binder:642_12"
+ blocked_thread_tid: 2720
+ blocking_thread_tid: 661
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4405,7 +5008,10 @@
waiter_count: 0
blocking_thread_name: "android.ui"
blocked_thread_name: "binder:642_12"
+ blocked_thread_tid: 2720
+ blocking_thread_tid: 661
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4432,7 +5038,10 @@
waiter_count: 0
blocking_thread_name: "android.ui"
blocked_thread_name: "binder:642_2"
+ blocked_thread_tid: 658
+ blocking_thread_tid: 661
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4459,7 +5068,10 @@
waiter_count: 0
blocking_thread_name: "android.ui"
blocked_thread_name: "binder:642_A"
+ blocked_thread_tid: 1675
+ blocking_thread_tid: 661
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4481,7 +5093,10 @@
waiter_count: 0
blocking_thread_name: "android.ui"
blocked_thread_name: "binder:642_8"
+ blocked_thread_tid: 1548
+ blocking_thread_tid: 661
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4508,7 +5123,10 @@
waiter_count: 0
blocking_thread_name: "android.ui"
blocked_thread_name: "binder:642_13"
+ blocked_thread_tid: 2721
+ blocking_thread_tid: 661
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4530,7 +5148,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_13"
blocked_thread_name: "binder:642_12"
+ blocked_thread_tid: 2720
+ blocking_thread_tid: 2721
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
binder_reply_ts: 1737229638872
@@ -4564,7 +5185,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_13"
blocked_thread_name: "binder:642_8"
+ blocked_thread_tid: 1548
+ blocking_thread_tid: 2721
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4591,7 +5215,10 @@
waiter_count: 1
blocking_thread_name: "binder:642_13"
blocked_thread_name: "binder:642_A"
+ blocked_thread_tid: 1675
+ blocking_thread_tid: 2721
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4628,7 +5255,10 @@
waiter_count: 2
blocking_thread_name: "binder:642_13"
blocked_thread_name: "binder:642_E"
+ blocked_thread_tid: 1934
+ blocking_thread_tid: 2721
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4650,7 +5280,10 @@
waiter_count: 0
blocking_thread_name: "android.ui"
blocked_thread_name: "binder:642_8"
+ blocked_thread_tid: 1548
+ blocking_thread_tid: 661
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4672,7 +5305,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_A"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1675
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4699,7 +5335,10 @@
waiter_count: 0
blocking_thread_name: "android.ui"
blocked_thread_name: "binder:642_E"
+ blocked_thread_tid: 1934
+ blocking_thread_tid: 661
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4721,7 +5360,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -4743,7 +5385,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -4770,7 +5415,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -4797,7 +5445,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -4824,7 +5475,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -4851,7 +5505,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -4878,7 +5535,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -4905,7 +5565,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -4932,7 +5595,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -4959,7 +5625,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -4986,7 +5655,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -5013,7 +5685,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -5040,7 +5715,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -5067,7 +5745,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -5094,7 +5775,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -5121,7 +5805,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -5148,7 +5835,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -5175,7 +5865,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5212,7 +5905,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
}
@@ -5229,7 +5925,10 @@
waiter_count: 0
blocking_thread_name: "StorageManagerService"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 672
+ blocking_thread_tid: 743
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5256,7 +5955,10 @@
waiter_count: 0
blocking_thread_name: "StorageManagerService"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 743
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5283,7 +5985,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "tworkPolicy.uid"
+ blocked_thread_tid: 1193
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5310,7 +6015,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5337,7 +6045,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5359,7 +6070,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5386,7 +6100,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5413,7 +6130,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5440,7 +6160,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5467,7 +6190,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5494,7 +6220,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5521,7 +6250,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5548,7 +6280,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5575,7 +6310,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5602,7 +6340,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5629,7 +6370,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5656,7 +6400,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5683,7 +6430,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5710,7 +6460,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5737,7 +6490,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5764,7 +6520,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5791,7 +6550,10 @@
waiter_count: 0
blocking_thread_name: "StorageManagerService"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 743
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5818,7 +6580,10 @@
waiter_count: 0
blocking_thread_name: "StorageManagerService"
blocked_thread_name: "PackageManager"
+ blocked_thread_tid: 693
+ blocking_thread_tid: 743
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5845,7 +6610,10 @@
waiter_count: 0
blocking_thread_name: "StorageManagerService"
blocked_thread_name: "tworkPolicy.uid"
+ blocked_thread_tid: 1193
+ blocking_thread_tid: 743
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5872,7 +6640,10 @@
waiter_count: 0
blocking_thread_name: "StorageManagerService"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 743
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5899,7 +6670,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -5926,7 +6700,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 670
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -5953,7 +6730,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "batterystats-ha"
+ blocked_thread_tid: 676
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -5980,7 +6760,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "batterystats-ha"
+ blocked_thread_tid: 676
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6007,7 +6790,10 @@
waiter_count: 0
blocking_thread_name: "StorageManagerService"
blocked_thread_name: "android.fg"
+ blocked_thread_tid: 660
+ blocking_thread_tid: 743
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6034,7 +6820,10 @@
waiter_count: 0
blocking_thread_name: "StorageManagerService"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 743
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -6076,7 +6865,10 @@
waiter_count: 1
blocking_thread_name: "StorageManagerService"
blocked_thread_name: "binder:642_1"
+ blocked_thread_tid: 657
+ blocking_thread_tid: 743
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
binder_reply_ts: 1739927686578
@@ -6115,7 +6907,10 @@
waiter_count: 2
blocking_thread_name: "StorageManagerService"
blocked_thread_name: "binder:642_E"
+ blocked_thread_tid: 1934
+ blocking_thread_tid: 743
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
binder_reply_ts: 1739931677940
@@ -6134,7 +6929,10 @@
waiter_count: 1
blocking_thread_name: "binder:642_E"
blocked_thread_name: "StorageManagerS"
+ blocked_thread_tid: 743
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6161,7 +6959,10 @@
waiter_count: 2
blocking_thread_name: "binder:642_E"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
}
@@ -6178,7 +6979,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "PowerManagerSer"
+ blocked_thread_tid: 687
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6200,7 +7004,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6227,7 +7034,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "PackageManager"
+ blocked_thread_tid: 693
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6254,7 +7064,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6281,7 +7094,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6308,7 +7124,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "binder:642_1"
+ blocked_thread_tid: 657
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6335,7 +7154,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6352,7 +7174,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6369,7 +7194,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6386,7 +7214,10 @@
waiter_count: 1
blocking_thread_name: "binder:642_E"
blocked_thread_name: "binder:642_13"
+ blocked_thread_tid: 2721
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
binder_reply_ts: 1739956996641
@@ -6415,7 +7246,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6432,7 +7266,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6449,7 +7286,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6466,7 +7306,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6483,7 +7326,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6500,7 +7346,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6517,7 +7366,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6534,7 +7386,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6551,7 +7406,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6568,7 +7426,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6585,7 +7446,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -6617,7 +7481,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "batterystats-ha"
+ blocked_thread_tid: 676
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6634,7 +7501,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "batterystats-ha"
+ blocked_thread_tid: 676
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6651,7 +7521,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "PowerManagerSer"
+ blocked_thread_tid: 687
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6668,7 +7541,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "PowerManagerSer"
+ blocked_thread_tid: 687
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -6685,7 +7561,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "fg"
+ blocked_thread_tid: 3516
+ blocking_thread_tid: 3519
process_name: "com.android.providers.media.module"
+ pid: 3487
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6712,7 +7591,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "binder:642_E"
+ blocked_thread_tid: 1934
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
binder_reply_ts: 1739981897430
@@ -6741,7 +7623,10 @@
waiter_count: 1
blocking_thread_name: "main"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -6778,7 +7663,10 @@
waiter_count: 2
blocking_thread_name: "main"
blocked_thread_name: "StorageManagerS"
+ blocked_thread_tid: 743
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -6800,7 +7688,10 @@
waiter_count: 3
blocking_thread_name: "main"
blocked_thread_name: "binder:642_13"
+ blocked_thread_tid: 2721
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
binder_reply_ts: 1739982622780
@@ -6819,7 +7710,10 @@
waiter_count: 3
blocking_thread_name: "binder:642_E"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -6841,7 +7735,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "fg"
+ blocked_thread_tid: 3516
+ blocking_thread_tid: 3487
process_name: "com.android.providers.media.module"
+ pid: 3487
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -6868,7 +7765,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "fg"
+ blocked_thread_tid: 3516
+ blocking_thread_tid: 3519
process_name: "com.android.providers.media.module"
+ pid: 3487
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6895,7 +7795,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_13"
blocked_thread_name: "system_server"
+ blocked_thread_tid: 642
+ blocking_thread_tid: 2721
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -6922,7 +7825,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "fg"
+ blocked_thread_tid: 3516
+ blocking_thread_tid: 3487
process_name: "com.android.providers.media.module"
+ pid: 3487
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -6949,7 +7855,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "fg"
+ blocked_thread_tid: 3516
+ blocking_thread_tid: 3519
process_name: "com.android.providers.media.module"
+ pid: 3487
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -6976,7 +7885,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "binder:642_1"
+ blocked_thread_tid: 657
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
binder_reply_ts: 1740012085111
@@ -7010,7 +7922,10 @@
waiter_count: 0
blocking_thread_name: "android.bg"
blocked_thread_name: "fg"
+ blocked_thread_tid: 3516
+ blocking_thread_tid: 3519
process_name: "com.android.providers.media.module"
+ pid: 3487
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7037,7 +7952,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "binder:642_13"
+ blocked_thread_tid: 2721
+ blocking_thread_tid: 642
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: true
binder_reply_ts: 1740024094690
@@ -7066,7 +7984,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "StorageManagerS"
+ blocked_thread_tid: 743
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7098,7 +8019,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -7115,7 +8039,10 @@
waiter_count: 1
blocking_thread_name: "binder:642_E"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7137,7 +8064,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -7154,7 +8084,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -7171,7 +8104,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_E"
blocked_thread_name: "tworkPolicy.uid"
+ blocked_thread_tid: 1193
+ blocking_thread_tid: 1934
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
}
@@ -7188,7 +8124,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "fg"
+ blocked_thread_tid: 3516
+ blocking_thread_tid: 3487
process_name: "com.android.providers.media.module"
+ pid: 3487
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -7215,7 +8154,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7242,7 +8184,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7269,7 +8214,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7296,7 +8244,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7323,7 +8274,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7350,7 +8304,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7377,7 +8334,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7404,7 +8364,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7431,7 +8394,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7458,7 +8424,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7485,7 +8454,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7512,7 +8484,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7539,7 +8514,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7566,7 +8544,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7593,7 +8574,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7620,7 +8604,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7647,7 +8634,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7674,7 +8664,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7701,7 +8694,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7728,7 +8724,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7755,7 +8754,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7782,7 +8784,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7809,7 +8814,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7836,7 +8844,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7863,7 +8874,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7890,7 +8904,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7917,7 +8934,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7944,7 +8964,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_1"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 657
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -7971,7 +8994,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -7998,7 +9024,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8025,7 +9054,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8052,7 +9084,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8079,7 +9114,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8106,7 +9144,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8133,7 +9174,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8160,7 +9204,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8187,7 +9234,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8214,7 +9264,10 @@
waiter_count: 0
blocking_thread_name: "android.ui"
blocked_thread_name: "android.bg"
+ blocked_thread_tid: 670
+ blocking_thread_tid: 661
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8246,7 +9299,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8273,7 +9329,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "ActivityManager"
+ blocked_thread_tid: 671
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8300,7 +9359,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8327,7 +9389,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8354,7 +9419,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8381,7 +9449,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8408,7 +9479,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8435,7 +9509,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8462,7 +9539,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8489,7 +9569,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8516,7 +9599,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8543,7 +9629,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8570,7 +9659,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8597,7 +9689,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8624,7 +9719,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8651,7 +9749,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8678,7 +9779,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8705,7 +9809,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8732,7 +9839,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8759,7 +9869,10 @@
waiter_count: 0
blocking_thread_name: "binder:642_8"
blocked_thread_name: "android.ui"
+ blocked_thread_tid: 661
+ blocking_thread_tid: 1548
process_name: "system_server"
+ pid: 642
is_blocked_thread_main: false
is_blocking_thread_main: false
thread_states {
@@ -8786,7 +9899,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8813,7 +9929,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8840,7 +9959,10 @@
waiter_count: 0
blocking_thread_name: "sAsyncHandlerThread"
blocked_thread_name: "d.process.media"
+ blocked_thread_tid: 2003
+ blocking_thread_tid: 2128
process_name: "android.process.media"
+ pid: 2003
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8867,7 +9989,10 @@
waiter_count: 0
blocking_thread_name: "SysUiBg"
blocked_thread_name: "ndroid.systemui"
+ blocked_thread_tid: 1253
+ blocking_thread_tid: 1331
process_name: "com.android.systemui"
+ pid: 1253
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8894,7 +10019,10 @@
waiter_count: 0
blocking_thread_name: "SysUiBg"
blocked_thread_name: "ndroid.systemui"
+ blocked_thread_tid: 1253
+ blocking_thread_tid: 1331
process_name: "com.android.systemui"
+ pid: 1253
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8921,7 +10049,10 @@
waiter_count: 0
blocking_thread_name: "SysUiBg"
blocked_thread_name: "ndroid.systemui"
+ blocked_thread_tid: 1253
+ blocking_thread_tid: 1331
process_name: "com.android.systemui"
+ pid: 1253
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8948,7 +10079,10 @@
waiter_count: 0
blocking_thread_name: "SysUiBg"
blocked_thread_name: "ndroid.systemui"
+ blocked_thread_tid: 1253
+ blocking_thread_tid: 1331
process_name: "com.android.systemui"
+ pid: 1253
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -8975,7 +10109,10 @@
waiter_count: 0
blocking_thread_name: "SysUiBg"
blocked_thread_name: "ndroid.systemui"
+ blocked_thread_tid: 1253
+ blocking_thread_tid: 1331
process_name: "com.android.systemui"
+ pid: 1253
is_blocked_thread_main: true
is_blocking_thread_main: false
thread_states {
@@ -9002,7 +10139,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "SysUiBg"
+ blocked_thread_tid: 1331
+ blocking_thread_tid: 1253
process_name: "com.android.systemui"
+ pid: 1253
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -9024,7 +10164,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "plugin"
+ blocked_thread_tid: 1341
+ blocking_thread_tid: 1253
process_name: "com.android.systemui"
+ pid: 1253
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
@@ -9051,7 +10194,10 @@
waiter_count: 0
blocking_thread_name: "main"
blocked_thread_name: "RenderThread"
+ blocked_thread_tid: 1436
+ blocking_thread_tid: 1253
process_name: "com.android.systemui"
+ pid: 1253
is_blocked_thread_main: false
is_blocking_thread_main: true
thread_states {
diff --git a/test/trace_processor/diff_tests/android/android_network_activity.out b/test/trace_processor/diff_tests/android/android_network_activity.out
new file mode 100644
index 0000000..14418e4
--- /dev/null
+++ b/test/trace_processor/diff_tests/android/android_network_activity.out
@@ -0,0 +1,4 @@
+"package_name","ts","dur","packet_count","packet_length"
+"uid=123",1000,1010,2,100
+"uid=123",3000,2500,4,200
+"uid=456",1005,1010,2,300
diff --git a/test/trace_processor/diff_tests/android/tests.py b/test/trace_processor/diff_tests/android/tests.py
index 25190b0..84bafc1 100644
--- a/test/trace_processor/diff_tests/android/tests.py
+++ b/test/trace_processor/diff_tests/android/tests.py
@@ -111,6 +111,157 @@
""",
out=Path('android_system_property_slice.out'))
+ def test_android_battery_stats_event_slices(self):
+ # The following has three events
+ # * top (123, mail) from 1000 to 9000 explicit
+ # * job (456, mail_job) starting at 3000 (end is inferred as trace end)
+ # * job (789, video_job) ending at 4000 (start is inferred as trace start)
+ return DiffTestBlueprint(
+ trace=TextProto(r"""
+ packet {
+ ftrace_events {
+ cpu: 1
+ event {
+ timestamp: 1000
+ pid: 1
+ print {
+ buf: "N|1000|battery_stats.top|+top=123:\"mail\"\n"
+ }
+ }
+ event {
+ timestamp: 3000
+ pid: 1
+ print {
+ buf: "N|1000|battery_stats.job|+job=456:\"mail_job\"\n"
+ }
+ }
+ event {
+ timestamp: 4000
+ pid: 1
+ print {
+ buf: "N|1000|battery_stats.job|-job=789:\"video_job\"\n"
+ }
+ }
+ event {
+ timestamp: 9000
+ pid: 1
+ print {
+ buf: "N|1000|battery_stats.top|-top=123:\"mail\"\n"
+ }
+ }
+ }
+ }
+ """),
+ query="""
+ SELECT IMPORT('android.battery_stats');
+ SELECT * FROM android_battery_stats_event_slices
+ ORDER BY str_value;
+ """,
+ out=Path('android_battery_stats_event_slices.out'))
+
+ def test_android_battery_stats_counters(self):
+ return DiffTestBlueprint(
+ trace=TextProto(r"""
+ packet {
+ ftrace_events {
+ cpu: 1
+ event {
+ timestamp: 1000
+ pid: 1
+ print {
+ buf: "C|1000|battery_stats.data_conn|13\n"
+ }
+ }
+ event {
+ timestamp: 4000
+ pid: 1
+ print {
+ buf: "C|1000|battery_stats.data_conn|20\n"
+ }
+ }
+ event {
+ timestamp: 1000
+ pid: 1
+ print {
+ buf: "C|1000|battery_stats.audio|1\n"
+ }
+ }
+ }
+ }
+ """),
+ query="""
+ SELECT IMPORT('android.battery_stats');
+ SELECT * FROM android_battery_stats_state
+ ORDER BY ts, track_name;
+ """,
+ out=Path('android_battery_stats_state.out'))
+
+ def test_android_network_activity(self):
+ # The following should have three activity regions:
+ # * uid=123 from 1000 to 2010 (note: end is max(ts)+idle_ns)
+ # * uid=456 from 1005 to 2015 (note: doesn't group with above due to name)
+ # * uid=123 from 3000 to 5500 (note: gap between 1010 to 3000 > idle_ns)
+ # Note: packet_timestamps are delta encoded from the base timestamp.
+ return DiffTestBlueprint(
+ trace=TextProto(r"""
+ packet {
+ timestamp: 0
+ network_packet_bundle {
+ ctx {
+ direction: DIR_EGRESS
+ interface: "wlan"
+ uid: 123
+ }
+ packet_timestamps: [
+ 1000, 1010,
+ 3000, 3050, 4000, 4500
+ ],
+ packet_lengths: [
+ 50, 50,
+ 50, 50, 50, 50
+ ],
+ }
+ }
+ packet {
+ timestamp: 0
+ network_packet_bundle {
+ ctx {
+ direction: DIR_EGRESS
+ interface: "wlan"
+ uid: 456
+ }
+ packet_timestamps: [1005, 1015]
+ packet_lengths: [100, 200]
+ }
+ }
+ packet {
+ timestamp: 0
+ network_packet_bundle {
+ ctx {
+ direction: DIR_INGRESS
+ interface: "loopback"
+ uid: 123
+ }
+ packet_timestamps: [6000]
+ packet_lengths: [100]
+ }
+ }
+ """),
+ query="""
+ SELECT RUN_METRIC(
+ 'android/network_activity_template.sql',
+ 'view_name', 'android_network_activity',
+ 'group_by', 'package_name',
+ 'filter', 'iface = "wlan"',
+ 'idle_ns', '1000',
+ 'quant_ns', '100'
+ );
+
+ SELECT * FROM android_network_activity
+ ORDER BY package_name, ts;
+ """,
+ out=Path('android_network_activity.out'))
+
def test_binder_sync_binder_metrics(self):
return DiffTestBlueprint(
trace=DataPath('android_binder_metric_trace.atr'),
diff --git a/test/trace_processor/diff_tests/chrome/chrome_scroll_check.py b/test/trace_processor/diff_tests/chrome/chrome_scroll_check.py
new file mode 100644
index 0000000..4c51da4
--- /dev/null
+++ b/test/trace_processor/diff_tests/chrome/chrome_scroll_check.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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()
+
+from chrome_scroll_helper import ChromeScrollHelper
+
+helper = ChromeScrollHelper(trace, start_id=1234, start_gesture_id=5678)
+
+# First scroll
+helper.begin(from_ms=0, dur_ms=10)
+helper.update(from_ms=15, dur_ms=10)
+helper.update(from_ms=30, dur_ms=10)
+helper.end(from_ms=45, dur_ms=10)
+
+# Second scroll
+helper.begin(from_ms=60, dur_ms=10)
+helper.update(from_ms=75, dur_ms=10)
+helper.end(from_ms=90, dur_ms=10)
+
+# Third scroll, won't have a GestureScrollEnd value.
+helper.begin(from_ms=120, dur_ms=10)
+helper.update(from_ms=135, dur_ms=10)
+helper.update(from_ms=150, dur_ms=10)
+helper.update(from_ms=150, dur_ms=10)
+helper.update(from_ms=180, dur_ms=10)
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/diff_tests/chrome/chrome_scroll_helper.py b/test/trace_processor/diff_tests/chrome/chrome_scroll_helper.py
new file mode 100644
index 0000000..7b7cee1
--- /dev/null
+++ b/test/trace_processor/diff_tests/chrome/chrome_scroll_helper.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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.
+
+import synth_common
+
+from synth_common import ms_to_ns
+trace = synth_common.create_trace()
+
+
+class ChromeScrollHelper:
+
+ 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
diff --git a/test/trace_processor/diff_tests/chrome/chrome_tasks.out b/test/trace_processor/diff_tests/chrome/chrome_tasks.out
index ef33837..7ca510e 100644
--- a/test/trace_processor/diff_tests/chrome/chrome_tasks.out
+++ b/test/trace_processor/diff_tests/chrome/chrome_tasks.out
@@ -16,7 +16,6 @@
"sendTouchEvent","java",194
"viz.mojom.CompositorFrameSinkClient message (hash=3114070324)","mojo",178
"viz.mojom.CompositorFrameSink message (hash=3089589715)","mojo",170
-"RunTask(posted_from=mojo/public/cpp/system/simple_watcher.cc:ArmOrNotify)","scheduler",158
"RunTask(posted_from=cc/scheduler/scheduler.cc:ScheduleBeginImplFrameDeadline)","scheduler",149
"RunTask(posted_from=net/quic/quic_chromium_alarm_factory.cc:SetImpl)","scheduler",135
"RunTask(posted_from=mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:SendMessage)","scheduler",114
@@ -25,6 +24,7 @@
"blink.mojom.WidgetInputHandler reply (hash=3392143105)","mojo",97
"tracing.mojom.ProducerHost message (hash=3013694824)","mojo",82
"RunTask(posted_from=net/disk_cache/simple/simple_entry_impl.cc:WriteDataInternal)","scheduler",81
+"RunTask(posted_from=mojo/public/cpp/system/simple_watcher.cc:ArmOrNotify)","mojo",74
"RunTask(posted_from=net/disk_cache/simple/simple_entry_impl.cc:CloseInternal)","scheduler",73
"RunTask(posted_from=base/android/task_scheduler/task_runner_android.cc:PostDelayedTask)","scheduler",63
"RunTask(posted_from=base/android/application_status_listener.cc:NotifyApplicationStateChange)","scheduler",54
@@ -37,16 +37,16 @@
"RunTask(posted_from=cc/trees/proxy_impl.cc:ScheduledActionSendBeginMainFrame)","scheduler",47
"RunTask(posted_from=cc/trees/proxy_main.cc:BeginMainFrame)","scheduler",47
"network.mojom.URLLoaderClient message (hash=374770486)","mojo",46
+"network.mojom.URLLoaderFactory message (hash=2397174083)","mojo",46
"viz.mojom.CompositorFrameSink message (hash=1654984935)","mojo",46
"RunTask(posted_from=components/update_client/component.cc:ChangeState)","scheduler",45
-"network.mojom.URLLoaderFactory message (hash=2397174083)","mojo",45
"Choreographer(java_views=OmniboxSuggestionsList)","choreographer",44
"RunTask(posted_from=net/disk_cache/simple/simple_entry_impl.cc:CreateEntryInternal)","scheduler",44
"network.mojom.ProxyConfigPollerClient message (hash=2347231843)","mojo",43
"blink.mojom.AssociatedInterfaceProvider message (hash=2648115757)","mojo",37
+"network.mojom.URLLoaderClient message (hash=3734484340)","mojo",35
"network.mojom.URLLoaderNetworkServiceObserver message (hash=3598259070)","mojo",35
"Looper.dispatch: com.android.internal.view.IInputConnectionWrapper$MyHandler(null)","other",34
"RunTask(posted_from=net/disk_cache/simple/simple_entry_impl.cc:OpenOrCreateEntryInternal)","scheduler",34
-"network.mojom.URLLoaderClient message (hash=3734484340)","mojo",34
+"network.mojom.URLLoaderClient message (hash=2503424824)","mojo",32
"RunTask(posted_from=components/update_client/component.cc:TransitionState)","scheduler",31
-"RunTask(posted_from=net/http/http_stream_factory_job.cc:RunLoop)","scheduler",31
diff --git a/test/trace_processor/diff_tests/chrome/scroll_jank_gpu_check.py b/test/trace_processor/diff_tests/chrome/scroll_jank_gpu_check.py
index 7e33ac2..c9ba45c 100644
--- a/test/trace_processor/diff_tests/chrome/scroll_jank_gpu_check.py
+++ b/test/trace_processor/diff_tests/chrome/scroll_jank_gpu_check.py
@@ -24,51 +24,9 @@
from synth_common import ms_to_ns
trace = synth_common.create_trace()
+from chrome_scroll_helper import ChromeScrollHelper
-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 = ChromeScrollHelper(trace, start_id=1234, start_gesture_id=5678)
helper.begin(from_ms=0, dur_ms=10)
helper.update(from_ms=15, dur_ms=10)
diff --git a/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py b/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
index c5fd3bc..62833c2 100644
--- a/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
+++ b/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
@@ -518,3 +518,25 @@
30000000,1
115000000,0
"""))
+
+ def test_chrome_scrolls(self):
+ return DiffTestBlueprint(
+ trace=Path('chrome_scroll_check.py'),
+ query="""
+ SELECT IMPORT('chrome.chrome_scrolls');
+
+ SELECT
+ id,
+ ts,
+ dur,
+ scroll_start_ts,
+ scroll_end_ts
+ FROM chrome_scrolls
+ ORDER by id;
+ """,
+ out=Csv("""
+ "id","ts","dur","scroll_start_ts","scroll_end_ts"
+ 5678,0,55000000,0,45000000
+ 5679,60000000,40000000,60000000,90000000
+ 5680,120000000,70000000,120000000,-1
+ """))
diff --git a/test/trace_processor/diff_tests/graphics/android_jank_cuj.out b/test/trace_processor/diff_tests/graphics/android_jank_cuj.out
index 5784a98..22045da 100644
--- a/test/trace_processor/diff_tests/graphics/android_jank_cuj.out
+++ b/test/trace_processor/diff_tests/graphics/android_jank_cuj.out
@@ -16,6 +16,7 @@
apk_version_code: 1
debuggable: false
}
+ pid: 1000
}
ts: 0
dur: 123000000
@@ -196,6 +197,7 @@
apk_version_code: 1
debuggable: false
}
+ pid: 1000
}
ts: 0
dur: 901000010
diff --git a/test/trace_processor/diff_tests/performance/frame_timeline_metric.out b/test/trace_processor/diff_tests/performance/frame_timeline_metric.out
index eac9136..1a034f0 100644
--- a/test/trace_processor/diff_tests/performance/frame_timeline_metric.out
+++ b/test/trace_processor/diff_tests/performance/frame_timeline_metric.out
@@ -6,6 +6,7 @@
process {
process {
name: "process1"
+ pid: 1001
}
total_frames: 2
missed_frames: 2
@@ -27,6 +28,7 @@
process {
process {
name: "process2"
+ pid: 1002
}
total_frames: 2
missed_frames: 1
@@ -48,6 +50,7 @@
process {
process {
name: "process3"
+ pid: 1003
}
total_frames: 2
missed_frames: 2
@@ -69,6 +72,7 @@
process {
process {
name: "process4"
+ pid: 1004
}
total_frames: 5
missed_frames: 4
diff --git a/test/trace_processor/diff_tests/power/tests_power_rails.py b/test/trace_processor/diff_tests/power/tests_power_rails.py
index 869604c..5085cd2 100644
--- a/test/trace_processor/diff_tests/power/tests_power_rails.py
+++ b/test/trace_processor/diff_tests/power/tests_power_rails.py
@@ -58,18 +58,18 @@
return DiffTestBlueprint(
trace=Path('power_rails.textproto'),
query="""
- SELECT ts, value, t.name AS name
+ SELECT ts, extract_arg(arg_set_id,'packet_ts') as packet_ts, value, t.name AS name
FROM counter c JOIN counter_track t ON t.id = c.track_id
ORDER BY ts
LIMIT 20;
""",
out=Csv("""
- "ts","value","name"
- 3000000,333.000000,"power.test_rail_uws"
- 3000000,0.000000,"power.test_rail_uws"
- 3000004,1000.000000,"Testing"
- 3000005,999.000000,"power.test_rail2_uws"
- 5000000,666.000000,"power.test_rail_uws"
+ "ts","packet_ts","value","name"
+ 3000000,3000003,333.000000,"power.test_rail_uws"
+ 3000000,3000005,0.000000,"power.test_rail_uws"
+ 3000004,"[NULL]",1000.000000,"Testing"
+ 3000005,3000005,999.000000,"power.test_rail2_uws"
+ 5000000,3000005,666.000000,"power.test_rail_uws"
"""))
def test_power_rails_well_known_power_rails(self):
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph.textproto b/test/trace_processor/diff_tests/profiling/heap_graph.textproto
index b3decef..a6e314b 100644
--- a/test/trace_processor/diff_tests/profiling/heap_graph.textproto
+++ b/test/trace_processor/diff_tests/profiling/heap_graph.textproto
@@ -21,7 +21,7 @@
pid: 2
rss_anon_kb: 1000
vm_swap_kb: 0
- oom_score_adj: 0
+ oom_score_adj: -800
}
}
}
diff --git a/test/trace_processor/diff_tests/profiling/heap_stats_closest_proc.out b/test/trace_processor/diff_tests/profiling/heap_stats_closest_proc.out
index 1ee09bf..9a78653 100644
--- a/test/trace_processor/diff_tests/profiling/heap_stats_closest_proc.out
+++ b/test/trace_processor/diff_tests/profiling/heap_stats_closest_proc.out
@@ -4,6 +4,7 @@
process {
name: "proc1"
uid: 1000
+ pid: 2
}
samples {
ts: 200000000
@@ -28,6 +29,7 @@
process {
name: "proc2"
uid: 1000
+ pid: 3
}
samples {
ts: 1500000000
diff --git a/test/trace_processor/diff_tests/profiling/java_heap_histogram.out b/test/trace_processor/diff_tests/profiling/java_heap_histogram.out
index 206dc7c..c5aaf49 100644
--- a/test/trace_processor/diff_tests/profiling/java_heap_histogram.out
+++ b/test/trace_processor/diff_tests/profiling/java_heap_histogram.out
@@ -3,7 +3,8 @@
upid: 2
process {
name: "system_server"
- uid: 1000
+ uid: 1000,
+ pid: 2
}
samples {
ts: 10
diff --git a/test/trace_processor/diff_tests/profiling/tests.py b/test/trace_processor/diff_tests/profiling/tests.py
index e56fbff..4c5c2e3 100644
--- a/test/trace_processor/diff_tests/profiling/tests.py
+++ b/test/trace_processor/diff_tests/profiling/tests.py
@@ -116,6 +116,7 @@
process {
name: "system_server"
uid: 1000
+ pid: 2
}
mappings {
path: "[anon: libc_malloc]"
diff --git a/test/trace_processor/diff_tests/profiling/tests_metrics.py b/test/trace_processor/diff_tests/profiling/tests_metrics.py
index cb210cf..9a4ff07 100644
--- a/test/trace_processor/diff_tests/profiling/tests_metrics.py
+++ b/test/trace_processor/diff_tests/profiling/tests_metrics.py
@@ -71,6 +71,7 @@
process {
name: "system_server"
uid: 1000
+ pid: 2
}
samples {
ts: 10
@@ -81,6 +82,7 @@
obj_count: 6
reachable_obj_count: 3
anon_rss_and_swap_size: 4096000
+ oom_score_adj: 0
roots {
root_type: "ROOT_JAVA_FRAME"
type_name: "DeobfuscatedA[]"
diff --git a/test/trace_processor/diff_tests/startup/android_startup.out b/test/trace_processor/diff_tests/startup/android_startup.out
index 48fa752..18b879c 100644
--- a/test/trace_processor/diff_tests/startup/android_startup.out
+++ b/test/trace_processor/diff_tests/startup/android_startup.out
@@ -42,7 +42,8 @@
package_name: "com.google.android.calendar"
apk_version_code: 123
debuggable: false
- }
+ },
+ pid: 3
}
report_fully_drawn {
dur_ns: 198
diff --git a/test/trace_processor/diff_tests/startup/android_startup_attribution.out b/test/trace_processor/diff_tests/startup/android_startup_attribution.out
index 8336103..ea96296 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_attribution.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_attribution.out
@@ -49,6 +49,10 @@
dur_ns: 499999845
dur_ms: 499.999845
}
+ time_dlopen_thread_main {
+ dur_ns: 2
+ dur_ms: 2e-06
+ }
}
activity_hosting_process_count: 1
process {
@@ -64,6 +68,7 @@
apk_version_code: 123
debuggable: false
}
+ pid: 3
}
event_timestamps {
intent_received: 100
@@ -110,6 +115,8 @@
name: "dl"
dur_ns: 5
}
+ dlopen_file: "libandroid.so"
+ dlopen_file: "libandroid2.so"
startup_type: "hot"
slow_start_reason: "GC Activity"
slow_start_reason: "Main Thread - Time spent in OpenDexFilesFromOat*"
diff --git a/test/trace_processor/diff_tests/startup/android_startup_attribution.py b/test/trace_processor/diff_tests/startup/android_startup_attribution.py
index 0d7e784..59301e0 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_attribution.py
+++ b/test/trace_processor/diff_tests/startup/android_startup_attribution.py
@@ -85,6 +85,15 @@
ts=5, pid=APP_PID, tid=APP_TID, buf='OpenDexFilesFromOat(nothing)')
trace.add_atrace_end(ts=35, pid=APP_PID, tid=APP_TID)
+# dlopen slices within the startup.
+trace.add_atrace_begin(
+ ts=166, pid=APP_PID, tid=APP_TID, buf='dlopen: libandroid.so')
+trace.add_atrace_end(ts=167, pid=APP_PID, tid=APP_TID)
+
+trace.add_atrace_begin(
+ ts=168, pid=APP_PID, tid=APP_TID, buf='dlopen: libandroid2.so')
+trace.add_atrace_end(ts=169, pid=APP_PID, tid=APP_TID)
+
trace.add_atrace_async_end(
ts=LAUNCH_END_TS,
tid=SYSTEM_SERVER_TID,
diff --git a/test/trace_processor/diff_tests/startup/android_startup_attribution_slow.out b/test/trace_processor/diff_tests/startup/android_startup_attribution_slow.out
index 80f6f81..4bf3fff 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_attribution_slow.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_attribution_slow.out
@@ -64,6 +64,7 @@
apk_version_code: 123
debuggable: false
}
+ pid: 3
}
event_timestamps {
intent_received: 100000000000
diff --git a/test/trace_processor/diff_tests/startup/android_startup_breakdown.out b/test/trace_processor/diff_tests/startup/android_startup_breakdown.out
index 52dd550..2f930d3 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_breakdown.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_breakdown.out
@@ -70,6 +70,7 @@
apk_version_code: 123
debuggable: false
}
+ pid: 3
}
activities {
name: "com.google.android.calendar.MainActivity"
diff --git a/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.out b/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.out
index 254759a..4417091 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.out
@@ -70,6 +70,7 @@
apk_version_code: 123
debuggable: false
}
+ pid: 3
}
activities {
name: "com.google.android.calendar.MainActivity"
diff --git a/test/trace_processor/diff_tests/startup/android_startup_lock_contention.out b/test/trace_processor/diff_tests/startup/android_startup_lock_contention.out
index e570b22..ba1311c 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_lock_contention.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_lock_contention.out
@@ -55,6 +55,7 @@
apk_version_code: 123
debuggable: false
}
+ pid: 3
}
event_timestamps {
intent_received: 110
diff --git a/test/trace_processor/diff_tests/startup/android_startup_lock_contention_slow.out b/test/trace_processor/diff_tests/startup/android_startup_lock_contention_slow.out
index cd5dc6c..aa4ec05 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_lock_contention_slow.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_lock_contention_slow.out
@@ -55,6 +55,7 @@
apk_version_code: 123
debuggable: false
}
+ pid: 3
}
event_timestamps {
intent_received: 110000000000
diff --git a/test/trace_processor/diff_tests/startup/android_startup_minsdk33.out b/test/trace_processor/diff_tests/startup/android_startup_minsdk33.out
index 1723d34..2a8307b 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_minsdk33.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_minsdk33.out
@@ -63,6 +63,7 @@
apk_version_code: 123
debuggable: true
}
+ pid: 3
}
event_timestamps {
intent_received: 220
diff --git a/test/trace_processor/diff_tests/startup/android_startup_process_track.out b/test/trace_processor/diff_tests/startup/android_startup_process_track.out
index 41b26e5..561fb0d 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_process_track.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_process_track.out
@@ -51,6 +51,7 @@
apk_version_code: 123
debuggable: false
}
+ pid: 3
}
event_timestamps {
intent_received: 100
@@ -118,6 +119,7 @@
apk_version_code: 123
debuggable: false
}
+ pid: 4
}
event_timestamps {
intent_received: 200
diff --git a/test/trace_processor/diff_tests/startup/android_startup_slow.out b/test/trace_processor/diff_tests/startup/android_startup_slow.out
index 53d53b9..f791fd6 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_slow.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_slow.out
@@ -43,6 +43,7 @@
apk_version_code: 123
debuggable: false
}
+ pid: 3
}
report_fully_drawn {
dur_ns: 198000000000
diff --git a/third_party/.gitignore b/third_party/.gitignore
new file mode 100644
index 0000000..1642854
--- /dev/null
+++ b/third_party/.gitignore
@@ -0,0 +1,3 @@
+clang-format/
+gn/
+ninja/
diff --git a/tools/gen_amalgamated b/tools/gen_amalgamated
index c529155..fac7f60 100755
--- a/tools/gen_amalgamated
+++ b/tools/gen_amalgamated
@@ -44,6 +44,7 @@
# line).
gn_args = ' '.join([
'enable_perfetto_ipc=true',
+ 'enable_perfetto_zlib=false',
'is_debug=false',
'is_perfetto_build_generator=true',
'is_perfetto_embedder=true',
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 5317914..179ac14 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -103,6 +103,7 @@
'//protos/perfetto/trace:perfetto_trace_protos',
'//src/trace_processor:demangle',
'//src/trace_processor:trace_processor_shell',
+ '//src/traced/service:traced',
]
target_vendor_available = [
diff --git a/tools/gen_bazel b/tools/gen_bazel
index 3121aa8..7461e4d 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -76,16 +76,23 @@
# exported publicly.
default_targets = [
'//src/base:perfetto_base_default_platform',
+ '//src/cloud_trace_processor:cloud_trace_processor',
'//src/ipc:perfetto_ipc',
'//src/ipc/protoc_plugin:ipc_plugin',
'//src/protozero:protozero',
- '//src/protozero/protoc_plugin:protozero_plugin',
'//src/protozero/protoc_plugin:cppgen_plugin',
- '//test:client_api_example',
+ '//src/protozero/protoc_plugin:protozero_plugin',
'//src/tools/proto_filter:proto_filter',
'//src/tools/proto_merger:proto_merger',
+ '//test:client_api_example',
] + public_targets
+# Proto targets are required by internal build rules but don't need to be
+# exported publicly.
+proto_default_targets = [
+ '//protos/perfetto/cloud_trace_processor:lite'
+]
+
# Proto target groups which will be made public.
proto_groups = {
'config': {
@@ -787,6 +794,10 @@
continue
gn.get_target(re.sub('(lite|zero|cpp|ipc)$', 'source_set', target.name))
+ # Discover all the default proto targets so it will be generated next.
+ for target in sorted(proto_default_targets):
+ gn.get_target(target)
+
# Generate targets for the transitive set of proto targets.
labels = [
l for target in sorted(itervalues(gn.proto_libs))
diff --git a/tools/gen_tp_table_docs.py b/tools/gen_tp_table_docs.py
index 97e183e..04339bf 100755
--- a/tools/gen_tp_table_docs.py
+++ b/tools/gen_tp_table_docs.py
@@ -27,6 +27,7 @@
#pylint: disable=wrong-import-position
from python.generators.trace_processor_table.public import ColumnDoc
+from python.generators.trace_processor_table.public import ColumnFlag
import python.generators.trace_processor_table.util as util
from python.generators.trace_processor_table.util import ParsedTable
from python.generators.trace_processor_table.util import ParsedColumn
@@ -43,6 +44,10 @@
if table.table.tabledoc.skip_id_and_type and is_skippable_col:
return None
+ # Ignore hidden columns in the documentation.
+ if ColumnFlag.HIDDEN in col.column.flags:
+ return None
+
# Our default assumption is the documentation for a column is a plain string
# so just make the comment for the column equal to that.
diff --git a/tools/install-build-deps b/tools/install-build-deps
index 255be95..c72eae9 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -23,6 +23,7 @@
import stat
import sys
import tempfile
+import time
import zipfile
from collections import namedtuple
@@ -60,6 +61,17 @@
'buildtools/emsdk', # Moved to buildtools/{mac,linux64}/emsdk
'buildtools/test_data', # Moved to test/data by r.android.com/1539381 .
'buildtools/d8', # Removed by r.android.com/1424334 .
+
+ # Build toools moved to third_party/ by r.android.com/2327602 .
+ 'buildtools/mac/clang-format',
+ 'buildtools/mac/gn',
+ 'buildtools/mac/ninja',
+ 'buildtools/linux64/clang-format',
+ 'buildtools/linux64/gn',
+ 'buildtools/linux64/ninja',
+ 'buildtools/win/clang-format.exe',
+ 'buildtools/win/gn.exe',
+ 'buildtools/win/ninja.exe',
]
# Dependencies required to build code on the host or when targeting desktop OS.
@@ -67,22 +79,22 @@
# GN. From https://chrome-infra-packages.appspot.com/dl/gn/gn/.
# git_revision:0725d7827575b239594fbc8fd5192873a1d62f44 .
Dependency(
- 'buildtools/mac/gn',
+ 'third_party/gn/gn',
'https://storage.googleapis.com/perfetto/gn-mac-1968-0725d782',
'9ced623a664560bba38bbadb9b91158ca4186358c847e17ab7d982b351373c2e',
'darwin', 'x64'),
Dependency(
- 'buildtools/mac/gn',
+ 'third_party/gn/gn',
'https://storage.googleapis.com/perfetto/gn-mac-arm64-1968-0725d782',
'd22336b5210b4dad5e36e8c28ce81187f491822cf4d8fd0a257b30d6bee3fd3f',
'darwin', 'arm64'),
Dependency(
- 'buildtools/linux64/gn',
+ 'third_party/gn/gn',
'https://storage.googleapis.com/perfetto/gn-linux64-1968-0725d782',
'f706aaa0676e3e22f5fc9ca482295d7caee8535d1869f99efa2358177b64f5cd',
'linux', 'x64'),
Dependency(
- 'buildtools/win/gn.exe',
+ 'third_party/gn/gn.exe',
'https://storage.googleapis.com/perfetto/gn-win-1968-0725d782',
'001f777f023c7a6959c778fb3a6b6cfc63f6baef953410ecdeaec350fb12285b',
'windows', 'x64'),
@@ -90,19 +102,19 @@
# clang-format
# From https://chromium.googlesource.com/chromium/src/buildtools/+/refs/heads/master/mac/clang-format.sha1
Dependency(
- 'buildtools/mac/clang-format',
+ 'third_party/clang-format/clang-format',
'https://storage.googleapis.com/chromium-clang-format/62bde1baa7196ad9df969fc1f06b66360b1a927b',
'6df686a937443cbe6efc013467a7ba5f98d3f187eb7765bb7abc6ce47626cf66',
'darwin', 'all'),
# From https://chromium.googlesource.com/chromium/src/buildtools/+/refs/heads/master/linux64/clang-format.sha1
Dependency(
- 'buildtools/linux64/clang-format',
+ 'third_party/clang-format/clang-format',
'https://storage.googleapis.com/chromium-clang-format/1baf0089e895c989a311b6a38ed94d0e8be4c0a7',
'd02a97a87e8c28898033aaf5986967b24dc47ebd5b376e1cd93e5009f22cd75e',
'linux', 'x64'),
# From https://chromium.googlesource.com/chromium/src/buildtools/+/refs/heads/master/win/clang-format.exe.sha1
Dependency(
- 'buildtools/win/clang-format.exe',
+ 'third_party/clang-format/clang-format.exe',
'https://storage.googleapis.com/chromium-clang-format/d4afd4eba27022f5f6d518133aebde57281677c9',
'2ba1b4d3ade90ea80316890b598ab5fc16777572be26afec6ce23117da121b80',
'windows', 'x64'),
@@ -115,17 +127,17 @@
# Ninja
Dependency(
- 'buildtools/mac/ninja',
+ 'third_party/ninja/ninja',
'https://storage.googleapis.com/perfetto/ninja-mac-x64_and_arm64-182',
'36e8b7aaa06911e1334feb664dd731a1cd69a15eb916a231a3d10ff65fca2c73',
'darwin', 'all'),
Dependency(
- 'buildtools/linux64/ninja',
+ 'third_party/ninja/ninja',
'https://storage.googleapis.com/perfetto/ninja-linux64-182',
'54ac6a01362190aaabf4cf276f9c8982cdf11b225438940fdde3339be0f2ecdc',
'linux', 'x64'),
Dependency(
- 'buildtools/win/ninja.exe',
+ 'third_party/ninja/ninja.exe',
'https://storage.googleapis.com/perfetto/ninja-win-182',
'09ced0fcd1a4dec7d1b798a2cf9ce5d20e5d2fbc2337343827f192ce47d0f491',
'windows', 'x64'),
@@ -399,8 +411,22 @@
TEST_DATA_SCRIPT = os.path.join(TOOLS_DIR, 'test_data')
+def CheckCallRetry(*args, **kwargs):
+ """ Like subprocess.check_call, with retries up to 5 times. """
+ MAX_ATTEMPTS = 5
+ for attempt in range(1, MAX_ATTEMPTS + 1):
+ try:
+ return subprocess.check_call(*args, **kwargs)
+ except subprocess.CalledProcessError as error:
+ if attempt == MAX_ATTEMPTS:
+ raise error
+ else:
+ logging.error(error)
+ time.sleep(attempt * 3)
+
+
def DownloadURL(url, out_file):
- subprocess.check_call(['curl', '-L', '-#', '-o', out_file, url])
+ CheckCallRetry(['curl', '-L', '-#', '-o', out_file, url])
def GetArch():
@@ -458,16 +484,23 @@
if not os.path.exists(path):
return
+ third_party_path = os.path.abspath(os.path.join(ROOT_DIR, 'third_party'))
buildtools_path = os.path.abspath(os.path.join(ROOT_DIR, 'buildtools'))
test_path = os.path.abspath(os.path.join(ROOT_DIR, 'test', 'data'))
if (not os.path.abspath(path).startswith(buildtools_path) and
- not os.path.abspath(path).startswith(test_path)):
+ not os.path.abspath(path).startswith(test_path) and
+ not os.path.abspath(path).startswith(third_party_path)):
# Safety check to prevent that some merge confilct ends up doing some
# rm -rf / or similar.
- logging.fatal('Cannot remove %s: outside of buildtools and test/data', path)
+ logging.fatal(
+ 'Cannot remove %s: outside of {buildtools, test/data, third_party}',
+ path)
sys.exit(1)
logging.info('Removing %s' % path)
- shutil.rmtree(path, onerror=del_read_only_for_windows)
+ if os.path.isdir(path):
+ shutil.rmtree(path, onerror=del_read_only_for_windows)
+ else:
+ os.remove(path)
def CheckoutGitRepo(path, git_url, revision, check_only):
@@ -480,10 +513,10 @@
MkdirRecursive(path)
logging.info('Fetching %s @ %s into %s', git_url, revision, path)
subprocess.check_call(['git', 'init', path], cwd=path)
- subprocess.check_call(
- ['git', 'fetch', '--quiet', '--depth', '1', git_url, revision], cwd=path)
+ CheckCallRetry(['git', 'fetch', '--quiet', '--depth', '1', git_url, revision],
+ cwd=path)
subprocess.check_call(['git', 'checkout', revision, '--quiet'], cwd=path)
- subprocess.check_call(
+ CheckCallRetry(
['git', 'submodule', 'update', '--init', '--recursive', '--quiet'],
cwd=path)
assert (IsGitRepoCheckoutOutAtRevision(path, revision))
@@ -538,6 +571,21 @@
dep.source_url, dep.checksum, actual_checksum))
+def CheckDepotToolsIsRecent():
+ gn_py_path = shutil.which('gn.py')
+ if gn_py_path is None:
+ return True # depot_tools doesn't seem to be installed in the PATH.
+ dt_dir = os.path.abspath(os.path.dirname(gn_py_path))
+ cmd = ['git', '-C', dt_dir, 'merge-base', '--is-ancestor', 'a0cf4321', 'HEAD']
+ git_ret = subprocess.call(cmd, stderr=subprocess.DEVNULL)
+ if git_ret == 0:
+ return True
+ print('\033[91mYour depot_tools revision is too old. Please run:\033[0m')
+ print('git -C %s fetch origin && git -C %s checkout -B main -t origin/main' %
+ (dt_dir, dt_dir))
+ return False
+
+
def Main():
parser = argparse.ArgumentParser()
parser.add_argument(
@@ -569,6 +617,9 @@
print('Building the UI on Windows is unsupported')
return 1
+ if not CheckDepotToolsIsRecent():
+ return 1
+
deps = BUILD_DEPS_HOST
if not args.no_toolchain:
deps += BUILD_DEPS_TOOLCHAIN_HOST
diff --git a/tools/run_buildtools_binary.py b/tools/run_buildtools_binary.py
index 6fcfe1a..1ce25a7 100644
--- a/tools/run_buildtools_binary.py
+++ b/tools/run_buildtools_binary.py
@@ -46,7 +46,13 @@
cmd = args[0]
args = args[1:]
- exe_path = os.path.join(ROOT_DIR, 'buildtools', os_dir, cmd) + ext
+
+ # Some binaries have been migrated to third_party/xxx. Look into that path
+ # first (see b/261398524)
+ exe_path = os.path.join(ROOT_DIR, 'third_party', cmd, cmd) + ext
+ if not os.path.exists(exe_path):
+ exe_path = os.path.join(ROOT_DIR, 'buildtools', os_dir, cmd) + ext
+
if sys_name == 'windows':
# execl() behaves oddly on Windows: the spawned process doesn't seem to
# receive CTRL+C. Use subprocess instead.
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 7dc51bd..1bd97da 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -32,7 +32,8 @@
"pako": "^1.0.11",
"protobufjs": "^6.9.0",
"util": "^0.12.3",
- "uuid": "^9.0.0"
+ "uuid": "^9.0.0",
+ "vega-lite": "^5.9.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.0.1",
@@ -1569,6 +1570,11 @@
"@types/har-format": "*"
}
},
+ "node_modules/@types/clone": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@types/clone/-/clone-2.1.1.tgz",
+ "integrity": "sha512-BZIU34bSYye0j/BFcPraiDZ5ka6MJADjcDVELGf7glr9K+iE8NYVjFslJFVWzskSxkLLyCrSPScE82/UUoBSvg=="
+ },
"node_modules/@types/color-convert": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-1.9.0.tgz",
@@ -1601,6 +1607,12 @@
"resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.29.tgz",
"integrity": "sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ=="
},
+ "node_modules/@types/geojson": {
+ "version": "7946.0.4",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.4.tgz",
+ "integrity": "sha512-MHmwBtCb7OCv1DSivz2UNJXPGU/1btAWRKlqJ2saEhVJkpkvqHMMaOpKg0v4sAbDWSQekHGvPVMM8nQ+Jen03Q==",
+ "peer": true
+ },
"node_modules/@types/graceful-fs": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz",
@@ -2164,7 +2176,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -2173,7 +2184,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -2914,6 +2924,14 @@
"wrap-ansi": "^6.2.0"
}
},
+ "node_modules/clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -2980,6 +2998,15 @@
"node": ">= 0.8"
}
},
+ "node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "peer": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
@@ -3093,6 +3120,229 @@
"resolved": "src/base/utils",
"link": true
},
+ "node_modules/d3-array": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.3.tgz",
+ "integrity": "sha512-JRHwbQQ84XuAESWhvIPaUV4/1UYTBOLiOPGWqgFDHZS1D5QN9c57FbH3QpEnQMYiOXNzKUQyGTZf+EVO7RT5TQ==",
+ "peer": true,
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-delaunay": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+ "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
+ "peer": true,
+ "dependencies": {
+ "delaunator": "5"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dispatch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
+ "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dsv": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
+ "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
+ "peer": true,
+ "dependencies": {
+ "commander": "7",
+ "iconv-lite": "0.6",
+ "rw": "1"
+ },
+ "bin": {
+ "csv2json": "bin/dsv2json.js",
+ "csv2tsv": "bin/dsv2dsv.js",
+ "dsv2dsv": "bin/dsv2dsv.js",
+ "dsv2json": "bin/dsv2json.js",
+ "json2csv": "bin/json2dsv.js",
+ "json2dsv": "bin/json2dsv.js",
+ "json2tsv": "bin/json2dsv.js",
+ "tsv2csv": "bin/dsv2dsv.js",
+ "tsv2json": "bin/dsv2json.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-force": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
+ "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
+ "peer": true,
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-quadtree": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-geo": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz",
+ "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "2.5.0 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-geo-projection": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-4.0.0.tgz",
+ "integrity": "sha512-p0bK60CEzph1iqmnxut7d/1kyTmm3UWtPlwdkM31AU+LW+BXazd5zJdoCn7VFxNCHXRngPHRnsNn5uGjLRGndg==",
+ "peer": true,
+ "dependencies": {
+ "commander": "7",
+ "d3-array": "1 - 3",
+ "d3-geo": "1.12.0 - 3"
+ },
+ "bin": {
+ "geo2svg": "bin/geo2svg.js",
+ "geograticule": "bin/geograticule.js",
+ "geoproject": "bin/geoproject.js",
+ "geoquantize": "bin/geoquantize.js",
+ "geostitch": "bin/geostitch.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-hierarchy": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
+ "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "peer": true,
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-quadtree": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
+ "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "peer": true,
+ "dependencies": {
+ "d3-path": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+ "peer": true,
+ "dependencies": {
+ "d3-time": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/data-urls": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz",
@@ -3236,6 +3486,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/delaunator": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz",
+ "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==",
+ "peer": true,
+ "dependencies": {
+ "robust-predicates": "^3.0.0"
+ }
+ },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -3355,14 +3614,12 @@
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/encoding": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
- "dev": true,
"optional": true,
"dependencies": {
"iconv-lite": "^0.6.2"
@@ -3741,7 +3998,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true,
"engines": {
"node": ">=6"
}
@@ -4337,8 +4593,7 @@
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-glob": {
"version": "3.2.12",
@@ -4371,8 +4626,7 @@
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"node_modules/fast-levenshtein": {
"version": "2.0.6",
@@ -4562,7 +4816,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@@ -4995,8 +5248,6 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "dev": true,
- "optional": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
@@ -5115,6 +5366,15 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/ip": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
@@ -5277,7 +5537,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -6358,6 +6617,11 @@
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
},
+ "node_modules/json-stringify-pretty-compact": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz",
+ "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA=="
+ },
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -6934,7 +7198,6 @@
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
- "dev": true,
"dependencies": {
"whatwg-url": "^5.0.0"
},
@@ -8274,7 +8537,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -8388,6 +8650,12 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/robust-predicates": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz",
+ "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==",
+ "peer": true
+ },
"node_modules/rollup": {
"version": "2.79.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
@@ -8491,6 +8759,12 @@
"queue-microtask": "^1.2.2"
}
},
+ "node_modules/rw": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
+ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
+ "peer": true
+ },
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -8523,8 +8797,7 @@
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/sane": {
"version": "4.1.0",
@@ -9590,7 +9863,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -9604,7 +9876,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -9886,11 +10157,30 @@
"node": ">=8.0"
}
},
+ "node_modules/topojson-client": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz",
+ "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==",
+ "peer": true,
+ "dependencies": {
+ "commander": "2"
+ },
+ "bin": {
+ "topo2geo": "bin/topo2geo",
+ "topomerge": "bin/topomerge",
+ "topoquantize": "bin/topoquantize"
+ }
+ },
+ "node_modules/topojson-client/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "peer": true
+ },
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
- "dev": true
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/trim-newlines": {
"version": "3.0.1",
@@ -9910,8 +10200,7 @@
"node_modules/tslib": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
- "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
- "dev": true
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
},
"node_modules/type-check": {
"version": "0.4.0",
@@ -10197,6 +10486,484 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "node_modules/vega": {
+ "version": "5.25.0",
+ "resolved": "https://registry.npmjs.org/vega/-/vega-5.25.0.tgz",
+ "integrity": "sha512-lr+uj0mhYlSN3JOKbMNp1RzZBenWp9DxJ7kR3lha58AFNCzzds7pmFa7yXPbtbaGhB7Buh/t6n+Bzk3Y0VnF5g==",
+ "peer": true,
+ "dependencies": {
+ "vega-crossfilter": "~4.1.1",
+ "vega-dataflow": "~5.7.5",
+ "vega-encode": "~4.9.2",
+ "vega-event-selector": "~3.0.1",
+ "vega-expression": "~5.1.0",
+ "vega-force": "~4.2.0",
+ "vega-format": "~1.1.1",
+ "vega-functions": "~5.13.2",
+ "vega-geo": "~4.4.1",
+ "vega-hierarchy": "~4.1.1",
+ "vega-label": "~1.2.1",
+ "vega-loader": "~4.5.1",
+ "vega-parser": "~6.2.0",
+ "vega-projection": "~1.6.0",
+ "vega-regression": "~1.2.0",
+ "vega-runtime": "~6.1.4",
+ "vega-scale": "~7.3.0",
+ "vega-scenegraph": "~4.10.2",
+ "vega-statistics": "~1.9.0",
+ "vega-time": "~2.1.1",
+ "vega-transforms": "~4.10.2",
+ "vega-typings": "~0.24.0",
+ "vega-util": "~1.17.2",
+ "vega-view": "~5.11.1",
+ "vega-view-transforms": "~4.5.9",
+ "vega-voronoi": "~4.2.1",
+ "vega-wordcloud": "~4.1.4"
+ }
+ },
+ "node_modules/vega-canvas": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/vega-canvas/-/vega-canvas-1.2.7.tgz",
+ "integrity": "sha512-OkJ9CACVcN9R5Pi9uF6MZBF06pO6qFpDYHWSKBJsdHP5o724KrsgR6UvbnXFH82FdsiTOff/HqjuaG8C7FL+9Q==",
+ "peer": true
+ },
+ "node_modules/vega-crossfilter": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/vega-crossfilter/-/vega-crossfilter-4.1.1.tgz",
+ "integrity": "sha512-yesvlMcwRwxrtAd9IYjuxWJJuAMI0sl7JvAFfYtuDkkGDtqfLXUcCzHIATqW6igVIE7tWwGxnbfvQLhLNgK44Q==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2",
+ "vega-dataflow": "^5.7.5",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-dataflow": {
+ "version": "5.7.5",
+ "resolved": "https://registry.npmjs.org/vega-dataflow/-/vega-dataflow-5.7.5.tgz",
+ "integrity": "sha512-EdsIl6gouH67+8B0f22Owr2tKDiMPNNR8lEvJDcxmFw02nXd8juimclpLvjPQriqn6ta+3Dn5txqfD117H04YA==",
+ "peer": true,
+ "dependencies": {
+ "vega-format": "^1.1.1",
+ "vega-loader": "^4.5.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-encode": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/vega-encode/-/vega-encode-4.9.2.tgz",
+ "integrity": "sha512-c3J0LYkgYeXQxwnYkEzL15cCFBYPRaYUon8O2SZ6O4PhH4dfFTXBzSyT8+gh8AhBd572l2yGDfxpEYA6pOqdjg==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2",
+ "d3-interpolate": "^3.0.1",
+ "vega-dataflow": "^5.7.5",
+ "vega-scale": "^7.3.0",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-event-selector": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/vega-event-selector/-/vega-event-selector-3.0.1.tgz",
+ "integrity": "sha512-K5zd7s5tjr1LiOOkjGpcVls8GsH/f2CWCrWcpKy74gTCp+llCdwz0Enqo013ZlGaRNjfgD/o1caJRt3GSaec4A=="
+ },
+ "node_modules/vega-expression": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/vega-expression/-/vega-expression-5.1.0.tgz",
+ "integrity": "sha512-u8Rzja/cn2PEUkhQN3zUj3REwNewTA92ExrcASNKUJPCciMkHJEjESwFYuI6DWMCq4hQElQ92iosOAtwzsSTqA==",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-expression/node_modules/@types/estree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
+ "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA=="
+ },
+ "node_modules/vega-force": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/vega-force/-/vega-force-4.2.0.tgz",
+ "integrity": "sha512-aE2TlP264HXM1r3fl58AvZdKUWBNOGkIvn4EWyqeJdgO2vz46zSU7x7TzPG4ZLuo44cDRU5Ng3I1eQk23Asz6A==",
+ "peer": true,
+ "dependencies": {
+ "d3-force": "^3.0.0",
+ "vega-dataflow": "^5.7.5",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-format": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/vega-format/-/vega-format-1.1.1.tgz",
+ "integrity": "sha512-Rll7YgpYbsgaAa54AmtEWrxaJqgOh5fXlvM2wewO4trb9vwM53KBv4Q/uBWCLK3LLGeBXIF6gjDt2LFuJAUtkQ==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2",
+ "d3-format": "^3.1.0",
+ "d3-time-format": "^4.1.0",
+ "vega-time": "^2.1.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-functions": {
+ "version": "5.13.2",
+ "resolved": "https://registry.npmjs.org/vega-functions/-/vega-functions-5.13.2.tgz",
+ "integrity": "sha512-YE1Xl3Qi28kw3vdXVYgKFMo20ttd3+SdKth1jUNtBDGGdrOpvPxxFhZkVqX+7FhJ5/1UkDoAYs/cZY0nRKiYgA==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2",
+ "d3-color": "^3.1.0",
+ "d3-geo": "^3.1.0",
+ "vega-dataflow": "^5.7.5",
+ "vega-expression": "^5.1.0",
+ "vega-scale": "^7.3.0",
+ "vega-scenegraph": "^4.10.2",
+ "vega-selections": "^5.4.1",
+ "vega-statistics": "^1.8.1",
+ "vega-time": "^2.1.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-geo": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/vega-geo/-/vega-geo-4.4.1.tgz",
+ "integrity": "sha512-s4WeZAL5M3ZUV27/eqSD3v0FyJz3PlP31XNSLFy4AJXHxHUeXT3qLiDHoVQnW5Om+uBCPDtTT1ROx1smGIf2aA==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2",
+ "d3-color": "^3.1.0",
+ "d3-geo": "^3.1.0",
+ "vega-canvas": "^1.2.7",
+ "vega-dataflow": "^5.7.5",
+ "vega-projection": "^1.6.0",
+ "vega-statistics": "^1.8.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-hierarchy": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/vega-hierarchy/-/vega-hierarchy-4.1.1.tgz",
+ "integrity": "sha512-h5mbrDtPKHBBQ9TYbvEb/bCqmGTlUX97+4CENkyH21tJs7naza319B15KRK0NWOHuhbGhFmF8T0696tg+2c8XQ==",
+ "peer": true,
+ "dependencies": {
+ "d3-hierarchy": "^3.1.2",
+ "vega-dataflow": "^5.7.5",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-label": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/vega-label/-/vega-label-1.2.1.tgz",
+ "integrity": "sha512-n/ackJ5lc0Xs9PInCaGumYn2awomPjJ87EMVT47xNgk2bHmJoZV1Ve/1PUM6Eh/KauY211wPMrNp/9Im+7Ripg==",
+ "peer": true,
+ "dependencies": {
+ "vega-canvas": "^1.2.6",
+ "vega-dataflow": "^5.7.3",
+ "vega-scenegraph": "^4.9.2",
+ "vega-util": "^1.15.2"
+ }
+ },
+ "node_modules/vega-lite": {
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/vega-lite/-/vega-lite-5.9.0.tgz",
+ "integrity": "sha512-VA3XDlF6nd/t46KDMfq8eNKOJKy9gpJuM+6CIl3jbWqS97jWXRWXp8DpUyDmbV+iq8n4hqNTaoPqDP/e03kifw==",
+ "dependencies": {
+ "@types/clone": "~2.1.1",
+ "clone": "~2.1.2",
+ "fast-deep-equal": "~3.1.3",
+ "fast-json-stable-stringify": "~2.1.0",
+ "json-stringify-pretty-compact": "~3.0.0",
+ "tslib": "~2.5.0",
+ "vega-event-selector": "~3.0.1",
+ "vega-expression": "~5.1.0",
+ "vega-util": "~1.17.2",
+ "yargs": "~17.7.1"
+ },
+ "bin": {
+ "vl2pdf": "bin/vl2pdf",
+ "vl2png": "bin/vl2png",
+ "vl2svg": "bin/vl2svg",
+ "vl2vg": "bin/vl2vg"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "vega": "^5.24.0"
+ }
+ },
+ "node_modules/vega-lite/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vega-lite/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/vega-lite/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/vega-lite/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vega-lite/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vega-loader": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/vega-loader/-/vega-loader-4.5.1.tgz",
+ "integrity": "sha512-qy5x32SaT0YkEujQM2yKqvLGV9XWQ2aEDSugBFTdYzu/1u4bxdUSRDREOlrJ9Km3RWIOgFiCkobPmFxo47SKuA==",
+ "peer": true,
+ "dependencies": {
+ "d3-dsv": "^3.0.1",
+ "node-fetch": "^2.6.7",
+ "topojson-client": "^3.1.0",
+ "vega-format": "^1.1.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-parser": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/vega-parser/-/vega-parser-6.2.0.tgz",
+ "integrity": "sha512-as+QnX8Qxe9q51L1C2sVBd+YYYctP848+zEvkBT2jlI2g30aZ6Uv7sKsq7QTL6DUbhXQKR0XQtzlanckSFdaOQ==",
+ "peer": true,
+ "dependencies": {
+ "vega-dataflow": "^5.7.5",
+ "vega-event-selector": "^3.0.1",
+ "vega-functions": "^5.13.1",
+ "vega-scale": "^7.3.0",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-projection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/vega-projection/-/vega-projection-1.6.0.tgz",
+ "integrity": "sha512-LGUaO/kpOEYuTlul+x+lBzyuL9qmMwP1yShdUWYLW+zXoeyGbs5OZW+NbPPwLYqJr5lpXDr/vGztFuA/6g2xvQ==",
+ "peer": true,
+ "dependencies": {
+ "d3-geo": "^3.1.0",
+ "d3-geo-projection": "^4.0.0",
+ "vega-scale": "^7.3.0"
+ }
+ },
+ "node_modules/vega-regression": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/vega-regression/-/vega-regression-1.2.0.tgz",
+ "integrity": "sha512-6TZoPlhV/280VbxACjRKqlE0Nv48z5g4CSNf1FmGGTWS1rQtElPTranSoVW4d7ET5eVQ6f9QLxNAiALptvEq+g==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2",
+ "vega-dataflow": "^5.7.3",
+ "vega-statistics": "^1.9.0",
+ "vega-util": "^1.15.2"
+ }
+ },
+ "node_modules/vega-runtime": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/vega-runtime/-/vega-runtime-6.1.4.tgz",
+ "integrity": "sha512-0dDYXyFLQcxPQ2OQU0WuBVYLRZnm+/CwVu6i6N4idS7R9VXIX5581EkCh3pZ20pQ/+oaA7oJ0pR9rJgJ6rukRQ==",
+ "peer": true,
+ "dependencies": {
+ "vega-dataflow": "^5.7.5",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-scale": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/vega-scale/-/vega-scale-7.3.0.tgz",
+ "integrity": "sha512-pMOAI2h+e1z7lsqKG+gMfR6NKN2sTcyjZbdJwntooW0uFHwjLGjMSY7kSd3nSEquF0HQ8qF7zR6gs1eRwlGimw==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "vega-time": "^2.1.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-scenegraph": {
+ "version": "4.10.2",
+ "resolved": "https://registry.npmjs.org/vega-scenegraph/-/vega-scenegraph-4.10.2.tgz",
+ "integrity": "sha512-R8m6voDZO5+etwNMcXf45afVM3XAtokMqxuDyddRl9l1YqSJfS+3u8hpolJ50c2q6ZN20BQiJwKT1o0bB7vKkA==",
+ "peer": true,
+ "dependencies": {
+ "d3-path": "^3.1.0",
+ "d3-shape": "^3.2.0",
+ "vega-canvas": "^1.2.7",
+ "vega-loader": "^4.5.1",
+ "vega-scale": "^7.3.0",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-selections": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/vega-selections/-/vega-selections-5.4.1.tgz",
+ "integrity": "sha512-EtYc4DvA+wXqBg9tq+kDomSoVUPCmQfS7hUxy2qskXEed79YTimt3Hcl1e1fW226I4AVDBEqTTKebmKMzbSgAA==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "3.2.2",
+ "vega-expression": "^5.0.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-selections/node_modules/d3-array": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.2.tgz",
+ "integrity": "sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==",
+ "peer": true,
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vega-statistics": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/vega-statistics/-/vega-statistics-1.9.0.tgz",
+ "integrity": "sha512-GAqS7mkatpXcMCQKWtFu1eMUKLUymjInU0O8kXshWaQrVWjPIO2lllZ1VNhdgE0qGj4oOIRRS11kzuijLshGXQ==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2"
+ }
+ },
+ "node_modules/vega-time": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/vega-time/-/vega-time-2.1.1.tgz",
+ "integrity": "sha512-z1qbgyX0Af2kQSGFbApwBbX2meenGvsoX8Nga8uyWN8VIbiySo/xqizz1KrP6NbB6R+x5egKmkjdnyNThPeEWA==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2",
+ "d3-time": "^3.1.0",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-transforms": {
+ "version": "4.10.2",
+ "resolved": "https://registry.npmjs.org/vega-transforms/-/vega-transforms-4.10.2.tgz",
+ "integrity": "sha512-sJELfEuYQ238PRG+GOqQch8D69RYnJevYSGLsRGQD2LxNz3j+GlUX6Pid+gUEH5HJy22Q5L0vsTl2ZNhIr4teQ==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2",
+ "vega-dataflow": "^5.7.5",
+ "vega-statistics": "^1.8.1",
+ "vega-time": "^2.1.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-typings": {
+ "version": "0.24.1",
+ "resolved": "https://registry.npmjs.org/vega-typings/-/vega-typings-0.24.1.tgz",
+ "integrity": "sha512-WNw6tDxwMsynQ9osJb3RZi3g8GZruxVgXfe8N7nbqvNOgDQkUuVjqTZiwGg5kqjmLqx09lRRlskgp/ov7lEGeg==",
+ "peer": true,
+ "dependencies": {
+ "@types/geojson": "7946.0.4",
+ "vega-event-selector": "^3.0.1",
+ "vega-expression": "^5.0.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-util": {
+ "version": "1.17.2",
+ "resolved": "https://registry.npmjs.org/vega-util/-/vega-util-1.17.2.tgz",
+ "integrity": "sha512-omNmGiZBdjm/jnHjZlywyYqafscDdHaELHx1q96n5UOz/FlO9JO99P4B3jZg391EFG8dqhWjQilSf2JH6F1mIw=="
+ },
+ "node_modules/vega-view": {
+ "version": "5.11.1",
+ "resolved": "https://registry.npmjs.org/vega-view/-/vega-view-5.11.1.tgz",
+ "integrity": "sha512-RoWxuoEMI7xVQJhPqNeLEHCezudsf3QkVMhH5tCovBqwBADQGqq9iWyax3ZzdyX1+P3eBgm7cnLvpqtN2hU8kA==",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "^3.2.2",
+ "d3-timer": "^3.0.1",
+ "vega-dataflow": "^5.7.5",
+ "vega-format": "^1.1.1",
+ "vega-functions": "^5.13.1",
+ "vega-runtime": "^6.1.4",
+ "vega-scenegraph": "^4.10.2",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-view-transforms": {
+ "version": "4.5.9",
+ "resolved": "https://registry.npmjs.org/vega-view-transforms/-/vega-view-transforms-4.5.9.tgz",
+ "integrity": "sha512-NxEq4ZD4QwWGRrl2yDLnBRXM9FgCI+vvYb3ZC2+nVDtkUxOlEIKZsMMw31op5GZpfClWLbjCT3mVvzO2xaTF+g==",
+ "peer": true,
+ "dependencies": {
+ "vega-dataflow": "^5.7.5",
+ "vega-scenegraph": "^4.10.2",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-voronoi": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/vega-voronoi/-/vega-voronoi-4.2.1.tgz",
+ "integrity": "sha512-zzi+fxU/SBad4irdLLsG3yhZgXWZezraGYVQfZFWe8kl7W/EHUk+Eqk/eetn4bDeJ6ltQskX+UXH3OP5Vh0Q0Q==",
+ "peer": true,
+ "dependencies": {
+ "d3-delaunay": "^6.0.2",
+ "vega-dataflow": "^5.7.5",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "node_modules/vega-wordcloud": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/vega-wordcloud/-/vega-wordcloud-4.1.4.tgz",
+ "integrity": "sha512-oeZLlnjiusLAU5vhk0IIdT5QEiJE0x6cYoGNq1th+EbwgQp153t4r026fcib9oq15glHFOzf81a8hHXHSJm1Jw==",
+ "peer": true,
+ "dependencies": {
+ "vega-canvas": "^1.2.7",
+ "vega-dataflow": "^5.7.5",
+ "vega-scale": "^7.3.0",
+ "vega-statistics": "^1.8.1",
+ "vega-util": "^1.17.1"
+ }
+ },
"node_modules/vlq": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
@@ -10237,8 +11004,7 @@
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
- "dev": true
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-encoding": {
"version": "1.0.5",
@@ -10271,7 +11037,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "dev": true,
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
@@ -11706,6 +12471,11 @@
"@types/har-format": "*"
}
},
+ "@types/clone": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@types/clone/-/clone-2.1.1.tgz",
+ "integrity": "sha512-BZIU34bSYye0j/BFcPraiDZ5ka6MJADjcDVELGf7glr9K+iE8NYVjFslJFVWzskSxkLLyCrSPScE82/UUoBSvg=="
+ },
"@types/color-convert": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-1.9.0.tgz",
@@ -11738,6 +12508,12 @@
"resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.29.tgz",
"integrity": "sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ=="
},
+ "@types/geojson": {
+ "version": "7946.0.4",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.4.tgz",
+ "integrity": "sha512-MHmwBtCb7OCv1DSivz2UNJXPGU/1btAWRKlqJ2saEhVJkpkvqHMMaOpKg0v4sAbDWSQekHGvPVMM8nQ+Jen03Q==",
+ "peer": true
+ },
"@types/graceful-fs": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz",
@@ -12161,14 +12937,12 @@
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"requires": {
"color-convert": "^2.0.1"
}
@@ -12711,6 +13485,11 @@
"wrap-ansi": "^6.2.0"
}
},
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
+ },
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -12761,6 +13540,12 @@
"delayed-stream": "~1.0.0"
}
},
+ "commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "peer": true
+ },
"commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
@@ -12860,6 +13645,157 @@
"custom_utils": {
"version": "file:src/base/utils"
},
+ "d3-array": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.3.tgz",
+ "integrity": "sha512-JRHwbQQ84XuAESWhvIPaUV4/1UYTBOLiOPGWqgFDHZS1D5QN9c57FbH3QpEnQMYiOXNzKUQyGTZf+EVO7RT5TQ==",
+ "peer": true,
+ "requires": {
+ "internmap": "1 - 2"
+ }
+ },
+ "d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "peer": true
+ },
+ "d3-delaunay": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+ "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
+ "peer": true,
+ "requires": {
+ "delaunator": "5"
+ }
+ },
+ "d3-dispatch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
+ "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
+ "peer": true
+ },
+ "d3-dsv": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
+ "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
+ "peer": true,
+ "requires": {
+ "commander": "7",
+ "iconv-lite": "0.6",
+ "rw": "1"
+ }
+ },
+ "d3-force": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
+ "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
+ "peer": true,
+ "requires": {
+ "d3-dispatch": "1 - 3",
+ "d3-quadtree": "1 - 3",
+ "d3-timer": "1 - 3"
+ }
+ },
+ "d3-format": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "peer": true
+ },
+ "d3-geo": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz",
+ "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==",
+ "peer": true,
+ "requires": {
+ "d3-array": "2.5.0 - 3"
+ }
+ },
+ "d3-geo-projection": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-4.0.0.tgz",
+ "integrity": "sha512-p0bK60CEzph1iqmnxut7d/1kyTmm3UWtPlwdkM31AU+LW+BXazd5zJdoCn7VFxNCHXRngPHRnsNn5uGjLRGndg==",
+ "peer": true,
+ "requires": {
+ "commander": "7",
+ "d3-array": "1 - 3",
+ "d3-geo": "1.12.0 - 3"
+ }
+ },
+ "d3-hierarchy": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
+ "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
+ "peer": true
+ },
+ "d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "peer": true,
+ "requires": {
+ "d3-color": "1 - 3"
+ }
+ },
+ "d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "peer": true
+ },
+ "d3-quadtree": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
+ "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
+ "peer": true
+ },
+ "d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "peer": true,
+ "requires": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ }
+ },
+ "d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "peer": true,
+ "requires": {
+ "d3-path": "^3.1.0"
+ }
+ },
+ "d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "peer": true,
+ "requires": {
+ "d3-array": "2 - 3"
+ }
+ },
+ "d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+ "peer": true,
+ "requires": {
+ "d3-time": "1 - 3"
+ }
+ },
+ "d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "peer": true
+ },
"data-urls": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz",
@@ -12966,6 +13902,15 @@
"isobject": "^3.0.1"
}
},
+ "delaunator": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz",
+ "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==",
+ "peer": true,
+ "requires": {
+ "robust-predicates": "^3.0.0"
+ }
+ },
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -13057,14 +14002,12 @@
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"encoding": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
- "dev": true,
"optional": true,
"requires": {
"iconv-lite": "^0.6.2"
@@ -13252,8 +14195,7 @@
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
"escape-string-regexp": {
"version": "4.0.0",
@@ -13707,8 +14649,7 @@
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fast-glob": {
"version": "3.2.12",
@@ -13737,8 +14678,7 @@
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"fast-levenshtein": {
"version": "2.0.6",
@@ -13890,8 +14830,7 @@
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"get-intrinsic": {
"version": "1.2.0",
@@ -14221,8 +15160,6 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "dev": true,
- "optional": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
@@ -14296,6 +15233,12 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
+ "internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "peer": true
+ },
"ip": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
@@ -14409,8 +15352,7 @@
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"is-generator-fn": {
"version": "2.1.0",
@@ -15246,6 +16188,11 @@
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
},
+ "json-stringify-pretty-compact": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz",
+ "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA=="
+ },
"json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -15698,7 +16645,6 @@
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
- "dev": true,
"requires": {
"whatwg-url": "^5.0.0"
}
@@ -16714,8 +17660,7 @@
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
},
"require-main-filename": {
"version": "2.0.0",
@@ -16796,6 +17741,12 @@
"glob": "^7.1.3"
}
},
+ "robust-predicates": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz",
+ "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==",
+ "peer": true
+ },
"rollup": {
"version": "2.79.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
@@ -16868,6 +17819,12 @@
"queue-microtask": "^1.2.2"
}
},
+ "rw": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
+ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
+ "peer": true
+ },
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -16886,8 +17843,7 @@
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sane": {
"version": "4.1.0",
@@ -17764,7 +18720,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -17775,7 +18730,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
@@ -17997,11 +18951,27 @@
"is-number": "^7.0.0"
}
},
+ "topojson-client": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz",
+ "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==",
+ "peer": true,
+ "requires": {
+ "commander": "2"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "peer": true
+ }
+ }
+ },
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
- "dev": true
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"trim-newlines": {
"version": "3.0.1",
@@ -18018,8 +18988,7 @@
"tslib": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
- "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
- "dev": true
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
},
"type-check": {
"version": "0.4.0",
@@ -18244,6 +19213,457 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "vega": {
+ "version": "5.25.0",
+ "resolved": "https://registry.npmjs.org/vega/-/vega-5.25.0.tgz",
+ "integrity": "sha512-lr+uj0mhYlSN3JOKbMNp1RzZBenWp9DxJ7kR3lha58AFNCzzds7pmFa7yXPbtbaGhB7Buh/t6n+Bzk3Y0VnF5g==",
+ "peer": true,
+ "requires": {
+ "vega-crossfilter": "~4.1.1",
+ "vega-dataflow": "~5.7.5",
+ "vega-encode": "~4.9.2",
+ "vega-event-selector": "~3.0.1",
+ "vega-expression": "~5.1.0",
+ "vega-force": "~4.2.0",
+ "vega-format": "~1.1.1",
+ "vega-functions": "~5.13.2",
+ "vega-geo": "~4.4.1",
+ "vega-hierarchy": "~4.1.1",
+ "vega-label": "~1.2.1",
+ "vega-loader": "~4.5.1",
+ "vega-parser": "~6.2.0",
+ "vega-projection": "~1.6.0",
+ "vega-regression": "~1.2.0",
+ "vega-runtime": "~6.1.4",
+ "vega-scale": "~7.3.0",
+ "vega-scenegraph": "~4.10.2",
+ "vega-statistics": "~1.9.0",
+ "vega-time": "~2.1.1",
+ "vega-transforms": "~4.10.2",
+ "vega-typings": "~0.24.0",
+ "vega-util": "~1.17.2",
+ "vega-view": "~5.11.1",
+ "vega-view-transforms": "~4.5.9",
+ "vega-voronoi": "~4.2.1",
+ "vega-wordcloud": "~4.1.4"
+ }
+ },
+ "vega-canvas": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/vega-canvas/-/vega-canvas-1.2.7.tgz",
+ "integrity": "sha512-OkJ9CACVcN9R5Pi9uF6MZBF06pO6qFpDYHWSKBJsdHP5o724KrsgR6UvbnXFH82FdsiTOff/HqjuaG8C7FL+9Q==",
+ "peer": true
+ },
+ "vega-crossfilter": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/vega-crossfilter/-/vega-crossfilter-4.1.1.tgz",
+ "integrity": "sha512-yesvlMcwRwxrtAd9IYjuxWJJuAMI0sl7JvAFfYtuDkkGDtqfLXUcCzHIATqW6igVIE7tWwGxnbfvQLhLNgK44Q==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2",
+ "vega-dataflow": "^5.7.5",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-dataflow": {
+ "version": "5.7.5",
+ "resolved": "https://registry.npmjs.org/vega-dataflow/-/vega-dataflow-5.7.5.tgz",
+ "integrity": "sha512-EdsIl6gouH67+8B0f22Owr2tKDiMPNNR8lEvJDcxmFw02nXd8juimclpLvjPQriqn6ta+3Dn5txqfD117H04YA==",
+ "peer": true,
+ "requires": {
+ "vega-format": "^1.1.1",
+ "vega-loader": "^4.5.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-encode": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/vega-encode/-/vega-encode-4.9.2.tgz",
+ "integrity": "sha512-c3J0LYkgYeXQxwnYkEzL15cCFBYPRaYUon8O2SZ6O4PhH4dfFTXBzSyT8+gh8AhBd572l2yGDfxpEYA6pOqdjg==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2",
+ "d3-interpolate": "^3.0.1",
+ "vega-dataflow": "^5.7.5",
+ "vega-scale": "^7.3.0",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-event-selector": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/vega-event-selector/-/vega-event-selector-3.0.1.tgz",
+ "integrity": "sha512-K5zd7s5tjr1LiOOkjGpcVls8GsH/f2CWCrWcpKy74gTCp+llCdwz0Enqo013ZlGaRNjfgD/o1caJRt3GSaec4A=="
+ },
+ "vega-expression": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/vega-expression/-/vega-expression-5.1.0.tgz",
+ "integrity": "sha512-u8Rzja/cn2PEUkhQN3zUj3REwNewTA92ExrcASNKUJPCciMkHJEjESwFYuI6DWMCq4hQElQ92iosOAtwzsSTqA==",
+ "requires": {
+ "@types/estree": "^1.0.0",
+ "vega-util": "^1.17.1"
+ },
+ "dependencies": {
+ "@types/estree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
+ "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA=="
+ }
+ }
+ },
+ "vega-force": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/vega-force/-/vega-force-4.2.0.tgz",
+ "integrity": "sha512-aE2TlP264HXM1r3fl58AvZdKUWBNOGkIvn4EWyqeJdgO2vz46zSU7x7TzPG4ZLuo44cDRU5Ng3I1eQk23Asz6A==",
+ "peer": true,
+ "requires": {
+ "d3-force": "^3.0.0",
+ "vega-dataflow": "^5.7.5",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-format": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/vega-format/-/vega-format-1.1.1.tgz",
+ "integrity": "sha512-Rll7YgpYbsgaAa54AmtEWrxaJqgOh5fXlvM2wewO4trb9vwM53KBv4Q/uBWCLK3LLGeBXIF6gjDt2LFuJAUtkQ==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2",
+ "d3-format": "^3.1.0",
+ "d3-time-format": "^4.1.0",
+ "vega-time": "^2.1.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-functions": {
+ "version": "5.13.2",
+ "resolved": "https://registry.npmjs.org/vega-functions/-/vega-functions-5.13.2.tgz",
+ "integrity": "sha512-YE1Xl3Qi28kw3vdXVYgKFMo20ttd3+SdKth1jUNtBDGGdrOpvPxxFhZkVqX+7FhJ5/1UkDoAYs/cZY0nRKiYgA==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2",
+ "d3-color": "^3.1.0",
+ "d3-geo": "^3.1.0",
+ "vega-dataflow": "^5.7.5",
+ "vega-expression": "^5.1.0",
+ "vega-scale": "^7.3.0",
+ "vega-scenegraph": "^4.10.2",
+ "vega-selections": "^5.4.1",
+ "vega-statistics": "^1.8.1",
+ "vega-time": "^2.1.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-geo": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/vega-geo/-/vega-geo-4.4.1.tgz",
+ "integrity": "sha512-s4WeZAL5M3ZUV27/eqSD3v0FyJz3PlP31XNSLFy4AJXHxHUeXT3qLiDHoVQnW5Om+uBCPDtTT1ROx1smGIf2aA==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2",
+ "d3-color": "^3.1.0",
+ "d3-geo": "^3.1.0",
+ "vega-canvas": "^1.2.7",
+ "vega-dataflow": "^5.7.5",
+ "vega-projection": "^1.6.0",
+ "vega-statistics": "^1.8.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-hierarchy": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/vega-hierarchy/-/vega-hierarchy-4.1.1.tgz",
+ "integrity": "sha512-h5mbrDtPKHBBQ9TYbvEb/bCqmGTlUX97+4CENkyH21tJs7naza319B15KRK0NWOHuhbGhFmF8T0696tg+2c8XQ==",
+ "peer": true,
+ "requires": {
+ "d3-hierarchy": "^3.1.2",
+ "vega-dataflow": "^5.7.5",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-label": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/vega-label/-/vega-label-1.2.1.tgz",
+ "integrity": "sha512-n/ackJ5lc0Xs9PInCaGumYn2awomPjJ87EMVT47xNgk2bHmJoZV1Ve/1PUM6Eh/KauY211wPMrNp/9Im+7Ripg==",
+ "peer": true,
+ "requires": {
+ "vega-canvas": "^1.2.6",
+ "vega-dataflow": "^5.7.3",
+ "vega-scenegraph": "^4.9.2",
+ "vega-util": "^1.15.2"
+ }
+ },
+ "vega-lite": {
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/vega-lite/-/vega-lite-5.9.0.tgz",
+ "integrity": "sha512-VA3XDlF6nd/t46KDMfq8eNKOJKy9gpJuM+6CIl3jbWqS97jWXRWXp8DpUyDmbV+iq8n4hqNTaoPqDP/e03kifw==",
+ "requires": {
+ "@types/clone": "~2.1.1",
+ "clone": "~2.1.2",
+ "fast-deep-equal": "~3.1.3",
+ "fast-json-stable-stringify": "~2.1.0",
+ "json-stringify-pretty-compact": "~3.0.0",
+ "tslib": "~2.5.0",
+ "vega-event-selector": "~3.0.1",
+ "vega-expression": "~5.1.0",
+ "vega-util": "~1.17.2",
+ "yargs": "~17.7.1"
+ },
+ "dependencies": {
+ "cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
+ },
+ "yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "requires": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="
+ }
+ }
+ },
+ "vega-loader": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/vega-loader/-/vega-loader-4.5.1.tgz",
+ "integrity": "sha512-qy5x32SaT0YkEujQM2yKqvLGV9XWQ2aEDSugBFTdYzu/1u4bxdUSRDREOlrJ9Km3RWIOgFiCkobPmFxo47SKuA==",
+ "peer": true,
+ "requires": {
+ "d3-dsv": "^3.0.1",
+ "node-fetch": "^2.6.7",
+ "topojson-client": "^3.1.0",
+ "vega-format": "^1.1.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-parser": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/vega-parser/-/vega-parser-6.2.0.tgz",
+ "integrity": "sha512-as+QnX8Qxe9q51L1C2sVBd+YYYctP848+zEvkBT2jlI2g30aZ6Uv7sKsq7QTL6DUbhXQKR0XQtzlanckSFdaOQ==",
+ "peer": true,
+ "requires": {
+ "vega-dataflow": "^5.7.5",
+ "vega-event-selector": "^3.0.1",
+ "vega-functions": "^5.13.1",
+ "vega-scale": "^7.3.0",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-projection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/vega-projection/-/vega-projection-1.6.0.tgz",
+ "integrity": "sha512-LGUaO/kpOEYuTlul+x+lBzyuL9qmMwP1yShdUWYLW+zXoeyGbs5OZW+NbPPwLYqJr5lpXDr/vGztFuA/6g2xvQ==",
+ "peer": true,
+ "requires": {
+ "d3-geo": "^3.1.0",
+ "d3-geo-projection": "^4.0.0",
+ "vega-scale": "^7.3.0"
+ }
+ },
+ "vega-regression": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/vega-regression/-/vega-regression-1.2.0.tgz",
+ "integrity": "sha512-6TZoPlhV/280VbxACjRKqlE0Nv48z5g4CSNf1FmGGTWS1rQtElPTranSoVW4d7ET5eVQ6f9QLxNAiALptvEq+g==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2",
+ "vega-dataflow": "^5.7.3",
+ "vega-statistics": "^1.9.0",
+ "vega-util": "^1.15.2"
+ }
+ },
+ "vega-runtime": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/vega-runtime/-/vega-runtime-6.1.4.tgz",
+ "integrity": "sha512-0dDYXyFLQcxPQ2OQU0WuBVYLRZnm+/CwVu6i6N4idS7R9VXIX5581EkCh3pZ20pQ/+oaA7oJ0pR9rJgJ6rukRQ==",
+ "peer": true,
+ "requires": {
+ "vega-dataflow": "^5.7.5",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-scale": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/vega-scale/-/vega-scale-7.3.0.tgz",
+ "integrity": "sha512-pMOAI2h+e1z7lsqKG+gMfR6NKN2sTcyjZbdJwntooW0uFHwjLGjMSY7kSd3nSEquF0HQ8qF7zR6gs1eRwlGimw==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "vega-time": "^2.1.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-scenegraph": {
+ "version": "4.10.2",
+ "resolved": "https://registry.npmjs.org/vega-scenegraph/-/vega-scenegraph-4.10.2.tgz",
+ "integrity": "sha512-R8m6voDZO5+etwNMcXf45afVM3XAtokMqxuDyddRl9l1YqSJfS+3u8hpolJ50c2q6ZN20BQiJwKT1o0bB7vKkA==",
+ "peer": true,
+ "requires": {
+ "d3-path": "^3.1.0",
+ "d3-shape": "^3.2.0",
+ "vega-canvas": "^1.2.7",
+ "vega-loader": "^4.5.1",
+ "vega-scale": "^7.3.0",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-selections": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/vega-selections/-/vega-selections-5.4.1.tgz",
+ "integrity": "sha512-EtYc4DvA+wXqBg9tq+kDomSoVUPCmQfS7hUxy2qskXEed79YTimt3Hcl1e1fW226I4AVDBEqTTKebmKMzbSgAA==",
+ "peer": true,
+ "requires": {
+ "d3-array": "3.2.2",
+ "vega-expression": "^5.0.1",
+ "vega-util": "^1.17.1"
+ },
+ "dependencies": {
+ "d3-array": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.2.tgz",
+ "integrity": "sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==",
+ "peer": true,
+ "requires": {
+ "internmap": "1 - 2"
+ }
+ }
+ }
+ },
+ "vega-statistics": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/vega-statistics/-/vega-statistics-1.9.0.tgz",
+ "integrity": "sha512-GAqS7mkatpXcMCQKWtFu1eMUKLUymjInU0O8kXshWaQrVWjPIO2lllZ1VNhdgE0qGj4oOIRRS11kzuijLshGXQ==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2"
+ }
+ },
+ "vega-time": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/vega-time/-/vega-time-2.1.1.tgz",
+ "integrity": "sha512-z1qbgyX0Af2kQSGFbApwBbX2meenGvsoX8Nga8uyWN8VIbiySo/xqizz1KrP6NbB6R+x5egKmkjdnyNThPeEWA==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2",
+ "d3-time": "^3.1.0",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-transforms": {
+ "version": "4.10.2",
+ "resolved": "https://registry.npmjs.org/vega-transforms/-/vega-transforms-4.10.2.tgz",
+ "integrity": "sha512-sJELfEuYQ238PRG+GOqQch8D69RYnJevYSGLsRGQD2LxNz3j+GlUX6Pid+gUEH5HJy22Q5L0vsTl2ZNhIr4teQ==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2",
+ "vega-dataflow": "^5.7.5",
+ "vega-statistics": "^1.8.1",
+ "vega-time": "^2.1.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-typings": {
+ "version": "0.24.1",
+ "resolved": "https://registry.npmjs.org/vega-typings/-/vega-typings-0.24.1.tgz",
+ "integrity": "sha512-WNw6tDxwMsynQ9osJb3RZi3g8GZruxVgXfe8N7nbqvNOgDQkUuVjqTZiwGg5kqjmLqx09lRRlskgp/ov7lEGeg==",
+ "peer": true,
+ "requires": {
+ "@types/geojson": "7946.0.4",
+ "vega-event-selector": "^3.0.1",
+ "vega-expression": "^5.0.1",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-util": {
+ "version": "1.17.2",
+ "resolved": "https://registry.npmjs.org/vega-util/-/vega-util-1.17.2.tgz",
+ "integrity": "sha512-omNmGiZBdjm/jnHjZlywyYqafscDdHaELHx1q96n5UOz/FlO9JO99P4B3jZg391EFG8dqhWjQilSf2JH6F1mIw=="
+ },
+ "vega-view": {
+ "version": "5.11.1",
+ "resolved": "https://registry.npmjs.org/vega-view/-/vega-view-5.11.1.tgz",
+ "integrity": "sha512-RoWxuoEMI7xVQJhPqNeLEHCezudsf3QkVMhH5tCovBqwBADQGqq9iWyax3ZzdyX1+P3eBgm7cnLvpqtN2hU8kA==",
+ "peer": true,
+ "requires": {
+ "d3-array": "^3.2.2",
+ "d3-timer": "^3.0.1",
+ "vega-dataflow": "^5.7.5",
+ "vega-format": "^1.1.1",
+ "vega-functions": "^5.13.1",
+ "vega-runtime": "^6.1.4",
+ "vega-scenegraph": "^4.10.2",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-view-transforms": {
+ "version": "4.5.9",
+ "resolved": "https://registry.npmjs.org/vega-view-transforms/-/vega-view-transforms-4.5.9.tgz",
+ "integrity": "sha512-NxEq4ZD4QwWGRrl2yDLnBRXM9FgCI+vvYb3ZC2+nVDtkUxOlEIKZsMMw31op5GZpfClWLbjCT3mVvzO2xaTF+g==",
+ "peer": true,
+ "requires": {
+ "vega-dataflow": "^5.7.5",
+ "vega-scenegraph": "^4.10.2",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-voronoi": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/vega-voronoi/-/vega-voronoi-4.2.1.tgz",
+ "integrity": "sha512-zzi+fxU/SBad4irdLLsG3yhZgXWZezraGYVQfZFWe8kl7W/EHUk+Eqk/eetn4bDeJ6ltQskX+UXH3OP5Vh0Q0Q==",
+ "peer": true,
+ "requires": {
+ "d3-delaunay": "^6.0.2",
+ "vega-dataflow": "^5.7.5",
+ "vega-util": "^1.17.1"
+ }
+ },
+ "vega-wordcloud": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/vega-wordcloud/-/vega-wordcloud-4.1.4.tgz",
+ "integrity": "sha512-oeZLlnjiusLAU5vhk0IIdT5QEiJE0x6cYoGNq1th+EbwgQp153t4r026fcib9oq15glHFOzf81a8hHXHSJm1Jw==",
+ "peer": true,
+ "requires": {
+ "vega-canvas": "^1.2.7",
+ "vega-dataflow": "^5.7.5",
+ "vega-scale": "^7.3.0",
+ "vega-statistics": "^1.8.1",
+ "vega-util": "^1.17.1"
+ }
+ },
"vlq": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
@@ -18280,8 +19700,7 @@
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
- "dev": true
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"whatwg-encoding": {
"version": "1.0.5",
@@ -18313,7 +19732,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "dev": true,
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
diff --git a/ui/package.json b/ui/package.json
index 0f4d69b..1257ab7 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -30,7 +30,8 @@
"pako": "^1.0.11",
"protobufjs": "^6.9.0",
"util": "^0.12.3",
- "uuid": "^9.0.0"
+ "uuid": "^9.0.0",
+ "vega-lite": "^5.9.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.0.1",
diff --git a/ui/release/channels.json b/ui/release/channels.json
index fb05de4..09f14f4 100644
--- a/ui/release/channels.json
+++ b/ui/release/channels.json
@@ -2,11 +2,11 @@
"channels": [
{
"name": "stable",
- "rev": "1f0f1aa6babb0b3ff273c5102aa677b2604e9a4e"
+ "rev": "1b8de44522f33d371def110325bf31b847c1f5c4"
},
{
"name": "canary",
- "rev": "056cc57893b57b82ed411256c2bd4091641f55fb"
+ "rev": "a34bc46479e2e659532f7e208c6eba5462c26bae"
},
{
"name": "autopush",
diff --git a/ui/src/assets/details.scss b/ui/src/assets/details.scss
index 9ba93b3..b5c131b 100644
--- a/ui/src/assets/details.scss
+++ b/ui/src/assets/details.scss
@@ -293,6 +293,7 @@
.details-table-multicolumn {
display: flex;
+ user-select: 'text';
}
.flow-link:hover {
diff --git a/ui/src/base/bigint_math.ts b/ui/src/base/bigint_math.ts
new file mode 100644
index 0000000..1860afe
--- /dev/null
+++ b/ui/src/base/bigint_math.ts
@@ -0,0 +1,77 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+export class BigintMath {
+ static INT64_MAX: bigint = (2n ** 63n) - 1n;
+
+ // Returns the smallest integral power of 2 that is not smaller than n.
+ // If n is less than or equal to 0, returns 1.
+ static bitCeil(n: bigint): bigint {
+ let result = 1n;
+ while (result < n) {
+ result <<= 1n;
+ }
+ return result;
+ };
+
+ // Returns the largest integral power of 2 which is not greater than n.
+ // If n is less than or equal to 0, returns 1.
+ static bitFloor(n: bigint): bigint {
+ let result = 1n;
+ while ((result << 1n) <= n) {
+ result <<= 1n;
+ }
+ return result;
+ };
+
+ // Returns the largest integral multiple of step which is not larger than n.
+ // If step is less than or equal to 0, returns n.
+ static quantizeFloor(n: bigint, step: bigint): bigint {
+ step = BigintMath.max(1n, step);
+ return step * (n / step);
+ }
+
+ // Return the integral multiple of step which is closest to n.
+ // If step is less than or equal to 0, returns n.
+ static quantize(n: bigint, step: bigint): bigint {
+ step = BigintMath.max(1n, step);
+ const halfStep = step / 2n;
+ return step * ((n + halfStep) / step);
+ }
+
+ // Return the greater of a and b
+ static max(a: bigint, b: bigint): bigint {
+ return a > b ? a : b;
+ }
+
+ // Return the smaller of a and b
+ static min(a: bigint, b: bigint): bigint {
+ return a < b ? a : b;
+ }
+
+ // Returns the number of 1 bits in n
+ static popcount(n: bigint): number {
+ if (n < 0n) {
+ throw Error(`Can\'t get popcount of negative number ${n}`);
+ }
+ let count = 0;
+ while (n) {
+ if (n & 1n) {
+ ++count;
+ }
+ n >>= 1n;
+ }
+ return count;
+ }
+}
diff --git a/ui/src/base/bigint_math_unittest.ts b/ui/src/base/bigint_math_unittest.ts
new file mode 100644
index 0000000..291eb32
--- /dev/null
+++ b/ui/src/base/bigint_math_unittest.ts
@@ -0,0 +1,141 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {
+ BigintMath as BIM,
+} from './bigint_math';
+
+describe('BigIntMath.bitCeil', () => {
+ it('rounds powers of 2 to themselves', () => {
+ expect(BIM.bitCeil(1n)).toBe(1n);
+ expect(BIM.bitCeil(2n)).toBe(2n);
+ expect(BIM.bitCeil(4n)).toBe(4n);
+ expect(BIM.bitCeil(4294967296n)).toBe(4294967296n);
+ expect(BIM.bitCeil(2305843009213693952n)).toBe(2305843009213693952n);
+ });
+
+ it('rounds non powers of 2 up to nearest power of 2', () => {
+ expect(BIM.bitCeil(3n)).toBe(4n);
+ expect(BIM.bitCeil(11n)).toBe(16n);
+ expect(BIM.bitCeil(33n)).toBe(64n);
+ expect(BIM.bitCeil(63n)).toBe(64n);
+ expect(BIM.bitCeil(1234567890123456789n)).toBe(2305843009213693952n);
+ });
+
+ it('rounds 0 or negative values up to 1', () => {
+ expect(BIM.bitCeil(0n)).toBe(1n);
+ expect(BIM.bitCeil(-123n)).toBe(1n);
+ });
+});
+
+describe('BigIntMath.bigFloor', () => {
+ it('rounds powers of 2 to themselves', () => {
+ expect(BIM.bitFloor(1n)).toBe(1n);
+ expect(BIM.bitFloor(2n)).toBe(2n);
+ expect(BIM.bitFloor(4n)).toBe(4n);
+ expect(BIM.bitFloor(4294967296n)).toBe(4294967296n);
+ expect(BIM.bitFloor(2305843009213693952n)).toBe(2305843009213693952n);
+ });
+
+ it('rounds non powers of 2 down to nearest power of 2', () => {
+ expect(BIM.bitFloor(3n)).toBe(2n);
+ expect(BIM.bitFloor(11n)).toBe(8n);
+ expect(BIM.bitFloor(33n)).toBe(32n);
+ expect(BIM.bitFloor(63n)).toBe(32n);
+ expect(BIM.bitFloor(1234567890123456789n)).toBe(1152921504606846976n);
+ });
+
+ it('rounds 0 or negative values up to 1', () => {
+ expect(BIM.bitFloor(0n)).toBe(1n);
+ expect(BIM.bitFloor(-123n)).toBe(1n);
+ });
+});
+
+describe('quantize', () => {
+ it('should quantize a number to the nearest multiple of a stepsize', () => {
+ expect(BIM.quantizeFloor(10n, 2n)).toEqual(10n);
+ expect(BIM.quantizeFloor(11n, 2n)).toEqual(10n);
+ expect(BIM.quantizeFloor(12n, 2n)).toEqual(12n);
+ expect(BIM.quantizeFloor(13n, 2n)).toEqual(12n);
+
+ expect(BIM.quantizeFloor(9n, 4n)).toEqual(8n);
+ expect(BIM.quantizeFloor(10n, 4n)).toEqual(8n);
+ expect(BIM.quantizeFloor(11n, 4n)).toEqual(8n);
+ expect(BIM.quantizeFloor(12n, 4n)).toEqual(12n);
+ expect(BIM.quantizeFloor(13n, 4n)).toEqual(12n);
+ });
+
+ it('should return value if stepsize is smaller than 1', () => {
+ expect(BIM.quantizeFloor(123n, 0n)).toEqual(123n);
+ expect(BIM.quantizeFloor(123n, -10n)).toEqual(123n);
+ });
+});
+
+describe('quantizeRound', () => {
+ it('should quantize a number to the nearest multiple of a stepsize', () => {
+ expect(BIM.quantize(0n, 2n)).toEqual(0n);
+ expect(BIM.quantize(1n, 2n)).toEqual(2n);
+ expect(BIM.quantize(2n, 2n)).toEqual(2n);
+ expect(BIM.quantize(3n, 2n)).toEqual(4n);
+ expect(BIM.quantize(4n, 2n)).toEqual(4n);
+
+ expect(BIM.quantize(0n, 3n)).toEqual(0n);
+ expect(BIM.quantize(1n, 3n)).toEqual(0n);
+ expect(BIM.quantize(2n, 3n)).toEqual(3n);
+ expect(BIM.quantize(3n, 3n)).toEqual(3n);
+ expect(BIM.quantize(4n, 3n)).toEqual(3n);
+ expect(BIM.quantize(5n, 3n)).toEqual(6n);
+ expect(BIM.quantize(6n, 3n)).toEqual(6n);
+ });
+
+ it('should return value if stepsize is smaller than 1', () => {
+ expect(BIM.quantize(123n, 0n)).toEqual(123n);
+ expect(BIM.quantize(123n, -10n)).toEqual(123n);
+ });
+});
+
+describe('max', () => {
+ it('should return the greater of two numbers', () => {
+ expect(BIM.max(5n, 8n)).toEqual(8n);
+ expect(BIM.max(3n, 7n)).toEqual(7n);
+ expect(BIM.max(6n, 6n)).toEqual(6n);
+ expect(BIM.max(-7n, -12n)).toEqual(-7n);
+ });
+});
+
+describe('min', () => {
+ it('should return the smaller of two numbers', () => {
+ expect(BIM.min(5n, 8n)).toEqual(5n);
+ expect(BIM.min(3n, 7n)).toEqual(3n);
+ expect(BIM.min(6n, 6n)).toEqual(6n);
+ expect(BIM.min(-7n, -12n)).toEqual(-12n);
+ });
+});
+
+describe('popcount', () => {
+ it('should return the number of set bits in an integer', () => {
+ expect(BIM.popcount(0n)).toBe(0);
+ expect(BIM.popcount(1n)).toBe(1);
+ expect(BIM.popcount(2n)).toBe(1);
+ expect(BIM.popcount(3n)).toBe(2);
+ expect(BIM.popcount(4n)).toBe(1);
+ expect(BIM.popcount(5n)).toBe(2);
+ expect(BIM.popcount(3462151285050974216n)).toBe(10);
+ });
+
+ it('should throw when presented with a negative integer', () => {
+ expect(() => BIM.popcount(-1n))
+ .toThrowError('Can\'t get popcount of negative number -1');
+ });
+});
diff --git a/ui/src/base/math_utils.ts b/ui/src/base/math_utils.ts
deleted file mode 100644
index f1c1816..0000000
--- a/ui/src/base/math_utils.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Round a number up to the nearest stepsize.
-export function roundUpNearest(val: number, stepsize: number): number {
- return stepsize * Math.ceil(val / stepsize);
-}
-
-// Round a number down to the nearest stepsize.
-export function roundDownNearest(val: number, stepsize: number): number {
- return stepsize * Math.floor(val / stepsize);
-}
diff --git a/ui/src/base/math_utils_unittest.ts b/ui/src/base/math_utils_unittest.ts
deleted file mode 100644
index 169b793..0000000
--- a/ui/src/base/math_utils_unittest.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {roundDownNearest, roundUpNearest} from './math_utils';
-
-describe('roundUpNearest()', () => {
- it('rounds decimal values up to the right step size', () => {
- expect(roundUpNearest(0.1, 0.5)).toBeCloseTo(0.5);
- expect(roundUpNearest(17.2, 0.5)).toBeCloseTo(17.5);
- });
-});
-
-describe('roundDownNearest()', () => {
- it('rounds decimal values down to the right step size', () => {
- expect(roundDownNearest(0.4, 0.5)).toBeCloseTo(0.0);
- expect(roundDownNearest(17.4, 0.5)).toBeCloseTo(17.0);
- });
-});
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 1e602fc..286f82f 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -61,7 +61,7 @@
UtidToTrackSortKey,
VisibleState,
} from './state';
-import {toNs} from './time';
+import {TPDuration, TPTime} from './time';
export const DEBUG_SLICE_TRACK_KIND = 'DebugSliceTrack';
@@ -89,8 +89,8 @@
}
export interface PostedScrollToRange {
- timeStart: number;
- timeEnd: number;
+ timeStart: TPTime;
+ timeEnd: TPTime;
viewPercentage?: number;
}
@@ -552,7 +552,7 @@
addAutomaticNote(
state: StateDraft,
- args: {timestamp: number, color: string, text: string}): void {
+ args: {timestamp: TPTime, color: string, text: string}): void {
const id = generateNextId(state);
state.notes[id] = {
noteType: 'DEFAULT',
@@ -563,7 +563,7 @@
};
},
- addNote(state: StateDraft, args: {timestamp: number, color: string}): void {
+ addNote(state: StateDraft, args: {timestamp: TPTime, color: string}): void {
const id = generateNextId(state);
state.notes[id] = {
noteType: 'DEFAULT',
@@ -606,14 +606,10 @@
},
markArea(state: StateDraft, args: {area: Area, persistent: boolean}): void {
+ const {start, end, tracks} = args.area;
+ assertTrue(start <= end);
const areaId = generateNextId(state);
- assertTrue(args.area.endSec >= args.area.startSec);
- state.areas[areaId] = {
- id: areaId,
- startSec: args.area.startSec,
- endSec: args.area.endSec,
- tracks: args.area.tracks,
- };
+ state.areas[areaId] = {id: areaId, start, end, tracks};
const noteId = args.persistent ? generateNextId(state) : '0';
const color = args.persistent ? randomColor() : '#344596';
state.notes[noteId] = {
@@ -667,7 +663,7 @@
selectCounter(
state: StateDraft,
- args: {leftTs: number, rightTs: number, id: number, trackId: string}):
+ args: {leftTs: TPTime, rightTs: TPTime, id: number, trackId: string}):
void {
state.currentSelection = {
kind: 'COUNTER',
@@ -680,7 +676,7 @@
selectHeapProfile(
state: StateDraft,
- args: {id: number, upid: number, ts: number, type: ProfileType}): void {
+ args: {id: number, upid: number, ts: TPTime, type: ProfileType}): void {
state.currentSelection = {
kind: 'HEAP_PROFILE',
id: args.id,
@@ -690,8 +686,8 @@
};
this.openFlamegraph(state, {
type: args.type,
- startNs: toNs(state.traceTime.startSec),
- endNs: args.ts,
+ start: state.traceTime.start,
+ end: args.ts,
upids: [args.upid],
viewingOption: DEFAULT_VIEWING_OPTION,
});
@@ -700,8 +696,8 @@
selectPerfSamples(state: StateDraft, args: {
id: number,
upid: number,
- leftTs: number,
- rightTs: number,
+ leftTs: TPTime,
+ rightTs: TPTime,
type: ProfileType
}): void {
state.currentSelection = {
@@ -714,8 +710,8 @@
};
this.openFlamegraph(state, {
type: args.type,
- startNs: args.leftTs,
- endNs: args.rightTs,
+ start: args.leftTs,
+ end: args.rightTs,
upids: [args.upid],
viewingOption: PERF_SAMPLES_KEY,
});
@@ -723,16 +719,16 @@
openFlamegraph(state: StateDraft, args: {
upids: number[],
- startNs: number,
- endNs: number,
+ start: TPTime,
+ end: TPTime,
type: ProfileType,
viewingOption: FlamegraphStateViewingOption
}): void {
state.currentFlamegraphState = {
kind: 'FLAMEGRAPH_STATE',
upids: args.upids,
- startNs: args.startNs,
- endNs: args.endNs,
+ start: args.start,
+ end: args.end,
type: args.type,
viewingOption: args.viewingOption,
focusRegex: '',
@@ -784,16 +780,33 @@
selectDebugSlice(state: StateDraft, args: {
id: number,
sqlTableName: string,
- startS: number,
- durationS: number,
+ start: TPTime,
+ duration: TPDuration,
trackId: string,
}): void {
state.currentSelection = {
kind: 'DEBUG_SLICE',
id: args.id,
sqlTableName: args.sqlTableName,
- startS: args.startS,
- durationS: args.durationS,
+ start: args.start,
+ duration: args.duration,
+ trackId: args.trackId,
+ };
+ },
+
+ selectTopLevelScrollSlice(state: StateDraft, args: {
+ id: number,
+ sqlTableName: string,
+ start: TPTime,
+ duration: TPTime,
+ trackId: string,
+ }): void {
+ state.currentSelection = {
+ kind: 'TOP_LEVEL_SCROLL',
+ id: args.id,
+ sqlTableName: args.sqlTableName,
+ start: args.start,
+ duration: args.duration,
trackId: args.trackId,
};
},
@@ -893,25 +906,17 @@
},
selectArea(state: StateDraft, args: {area: Area}): void {
+ const {start, end, tracks} = args.area;
+ assertTrue(start <= end);
const areaId = generateNextId(state);
- assertTrue(args.area.endSec >= args.area.startSec);
- state.areas[areaId] = {
- id: areaId,
- startSec: args.area.startSec,
- endSec: args.area.endSec,
- tracks: args.area.tracks,
- };
+ state.areas[areaId] = {id: areaId, start, end, tracks};
state.currentSelection = {kind: 'AREA', areaId};
},
editArea(state: StateDraft, args: {area: Area, areaId: string}): void {
- assertTrue(args.area.endSec >= args.area.startSec);
- state.areas[args.areaId] = {
- id: args.areaId,
- startSec: args.area.startSec,
- endSec: args.area.endSec,
- tracks: args.area.tracks,
- };
+ const {start, end, tracks} = args.area;
+ assertTrue(start <= end);
+ state.areas[args.areaId] = {id: args.areaId, start, end, tracks};
},
reSelectArea(state: StateDraft, args: {areaId: string, noteId: string}):
@@ -1031,11 +1036,11 @@
state.searchIndex = args.index;
},
- setHoverCursorTimestamp(state: StateDraft, args: {ts: number}) {
+ setHoverCursorTimestamp(state: StateDraft, args: {ts: TPTime}) {
state.hoverCursorTimestamp = args.ts;
},
- setHoveredNoteTimestamp(state: StateDraft, args: {ts: number}) {
+ setHoveredNoteTimestamp(state: StateDraft, args: {ts: TPTime}) {
state.hoveredNoteTimestamp = args.ts;
},
diff --git a/ui/src/common/actions_unittest.ts b/ui/src/common/actions_unittest.ts
index 6702e72..b613777 100644
--- a/ui/src/common/actions_unittest.ts
+++ b/ui/src/common/actions_unittest.ts
@@ -446,9 +446,13 @@
const state = createEmptyState();
const afterSelectingPerf = produce(state, (draft) => {
- StateActions.selectPerfSamples(
- draft,
- {id: 0, upid: 0, leftTs: 0, rightTs: 0, type: ProfileType.PERF_SAMPLE});
+ StateActions.selectPerfSamples(draft, {
+ id: 0,
+ upid: 0,
+ leftTs: 0n,
+ rightTs: 0n,
+ type: ProfileType.PERF_SAMPLE,
+ });
});
expect(assertExists(afterSelectingPerf.currentFlamegraphState).type)
@@ -460,7 +464,7 @@
const afterSelectingPerf = produce(state, (draft) => {
StateActions.selectHeapProfile(
- draft, {id: 0, upid: 0, ts: 0, type: ProfileType.JAVA_HEAP_GRAPH});
+ draft, {id: 0, upid: 0, ts: 0n, type: ProfileType.JAVA_HEAP_GRAPH});
});
expect(assertExists(afterSelectingPerf.currentFlamegraphState).type)
diff --git a/ui/src/common/empty_state.ts b/ui/src/common/empty_state.ts
index bd1e6b6..6d806a2 100644
--- a/ui/src/common/empty_state.ts
+++ b/ui/src/common/empty_state.ts
@@ -110,7 +110,7 @@
visibleState: {
...defaultTraceTime,
lastUpdate: 0,
- resolution: 0,
+ resolution: 0n,
},
},
@@ -142,8 +142,8 @@
sidebarVisible: true,
hoveredUtid: -1,
hoveredPid: -1,
- hoverCursorTimestamp: -1,
- hoveredNoteTimestamp: -1,
+ hoverCursorTimestamp: -1n,
+ hoveredNoteTimestamp: -1n,
highlightedSliceId: -1,
focusedFlowIdLeft: -1,
focusedFlowIdRight: -1,
diff --git a/ui/src/common/engine.ts b/ui/src/common/engine.ts
index 8b6cb46..861601f 100644
--- a/ui/src/common/engine.ts
+++ b/ui/src/common/engine.ts
@@ -24,18 +24,20 @@
QueryArgs,
ResetTraceProcessorArgs,
} from './protos';
-import {NUM, NUM_NULL, STR} from './query_result';
+import {LONG, LONG_NULL, NUM, STR} from './query_result';
import {
createQueryResult,
QueryError,
QueryResult,
WritableQueryResult,
} from './query_result';
-import {TimeSpan} from './time';
+import {TPTime, TPTimeSpan} from './time';
import TraceProcessorRpc = perfetto.protos.TraceProcessorRpc;
import TraceProcessorRpcStream = perfetto.protos.TraceProcessorRpcStream;
import TPM = perfetto.protos.TraceProcessorRpc.TraceProcessorMethod;
+import {Span} from '../common/time';
+import {BigintMath} from '../base/bigint_math';
export interface LoadingTracker {
beginLoading(): void;
@@ -410,38 +412,38 @@
return result.firstRow({cnt: NUM}).cnt;
}
- async getTraceTimeBounds(): Promise<TimeSpan> {
+ async getTraceTimeBounds(): Promise<Span<TPTime>> {
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,
+ startTs: LONG,
+ endTs: LONG,
});
- return new TimeSpan(bounds.startTs / 1e9, bounds.endTs / 1e9);
+ return new TPTimeSpan(bounds.startTs, bounds.endTs);
}
- async getTracingMetadataTimeBounds(): Promise<TimeSpan> {
+ async getTracingMetadataTimeBounds(): Promise<Span<TPTime>> {
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, 'intValue': NUM_NULL});
+ let startBound = 0n;
+ let endBound = BigintMath.INT64_MAX;
+ const it = queryRes.iter({'name': STR, 'intValue': LONG_NULL});
for (; it.valid(); it.next()) {
const columnName = it.name;
const timestamp = it.intValue;
if (timestamp === null) continue;
if (columnName === 'tracing_disabled_ns') {
- endBound = Math.min(endBound, timestamp / 1e9);
+ endBound = BigintMath.min(endBound, timestamp);
} else {
- startBound = Math.max(startBound, timestamp / 1e9);
+ startBound = BigintMath.max(startBound, timestamp);
}
}
- return new TimeSpan(startBound, endBound);
+ return new TPTimeSpan(startBound, endBound);
}
getProxy(tag: string): EngineProxy {
diff --git a/ui/src/common/high_precision_time.ts b/ui/src/common/high_precision_time.ts
new file mode 100644
index 0000000..927b7df
--- /dev/null
+++ b/ui/src/common/high_precision_time.ts
@@ -0,0 +1,258 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {Span, TPTime} from './time';
+
+export type RoundMode = 'round'|'floor'|'ceil';
+
+// Stores a time as a bigint and an offset which is capable of:
+// - Storing and reproducing "TPTime"s without losing precision.
+// - Storing time with sub-nanosecond precision.
+// This class is immutable - each operation returns a new object.
+export class HighPrecisionTime {
+ // Time in nanoseconds == base + offset
+ // offset is kept in the range 0 <= x < 1 to avoid losing precision
+ readonly base: bigint;
+ readonly offset: number;
+
+ static get ZERO(): HighPrecisionTime {
+ return new HighPrecisionTime(0n);
+ }
+
+ constructor(base: bigint = 0n, offset: number = 0) {
+ // Normalize offset to sit in the range 0.0 <= x < 1.0
+ const offsetFloor = Math.floor(offset);
+ this.base = base + BigInt(offsetFloor);
+ this.offset = offset - offsetFloor;
+ }
+
+ static fromTPTime(timestamp: TPTime): HighPrecisionTime {
+ return new HighPrecisionTime(timestamp, 0);
+ }
+
+ static fromNanos(nanos: number|bigint) {
+ if (typeof nanos === 'number') {
+ return new HighPrecisionTime(0n, nanos);
+ } else if (typeof nanos === 'bigint') {
+ return new HighPrecisionTime(nanos);
+ } else {
+ const value: never = nanos;
+ throw new Error(`Value ${value} is neither a number nor a bigint`);
+ }
+ }
+
+ static fromSeconds(seconds: number) {
+ const nanos = seconds * 1e9;
+ const offset = nanos - Math.floor(nanos);
+ return new HighPrecisionTime(BigInt(Math.floor(nanos)), offset);
+ }
+
+ static max(a: HighPrecisionTime, b: HighPrecisionTime): HighPrecisionTime {
+ return a.isGreaterThan(b) ? a : b;
+ }
+
+ static min(a: HighPrecisionTime, b: HighPrecisionTime): HighPrecisionTime {
+ return a.isLessThan(b) ? a : b;
+ }
+
+ toTPTime(roundMode: RoundMode = 'floor'): TPTime {
+ switch (roundMode) {
+ case 'round':
+ return this.base + BigInt(Math.round(this.offset));
+ case 'floor':
+ return this.base;
+ case 'ceil':
+ return this.base + BigInt(Math.ceil(this.offset));
+ default:
+ const exhaustiveCheck: never = roundMode;
+ throw new Error(`Unhandled roundMode case: ${exhaustiveCheck}`);
+ }
+ }
+
+ get nanos(): number {
+ // WARNING: Number(bigint) can be surprisingly slow.
+ // WARNING: Precision may be lost here.
+ return Number(this.base) + this.offset;
+ }
+
+ get seconds(): number {
+ // WARNING: Number(bigint) can be surprisingly slow.
+ // WARNING: Precision may be lost here.
+ return (Number(this.base) + this.offset) / 1e9;
+ }
+
+ add(other: HighPrecisionTime): HighPrecisionTime {
+ return new HighPrecisionTime(
+ this.base + other.base, this.offset + other.offset);
+ }
+
+ addNanos(nanos: number|bigint): HighPrecisionTime {
+ return this.add(HighPrecisionTime.fromNanos(nanos));
+ }
+
+ addSeconds(seconds: number): HighPrecisionTime {
+ return new HighPrecisionTime(this.base, this.offset + seconds * 1e9);
+ }
+
+ addTPTime(ts: TPTime): HighPrecisionTime {
+ return new HighPrecisionTime(this.base + ts, this.offset);
+ }
+
+ subtract(other: HighPrecisionTime): HighPrecisionTime {
+ return new HighPrecisionTime(
+ this.base - other.base, this.offset - other.offset);
+ }
+
+ subtractTPTime(ts: TPTime): HighPrecisionTime {
+ return this.addTPTime(-ts);
+ }
+
+ subtractNanos(nanos: number|bigint): HighPrecisionTime {
+ return this.add(HighPrecisionTime.fromNanos(-nanos));
+ }
+
+ divide(divisor: number): HighPrecisionTime {
+ return this.multiply(1 / divisor);
+ }
+
+ multiply(factor: number): HighPrecisionTime {
+ const factorFloor = Math.floor(factor);
+ const newBase = this.base * BigInt(factorFloor);
+ const additionalBit = Number(this.base) * (factor - factorFloor);
+ const newOffset = factor * this.offset + additionalBit;
+ return new HighPrecisionTime(newBase, newOffset);
+ }
+
+ // Return true if other time is within some epsilon, default 1 femtosecond
+ equals(other: HighPrecisionTime, epsilon: number = 1e-6): boolean {
+ return Math.abs(this.subtract(other).nanos) < epsilon;
+ }
+
+ isLessThan(other: HighPrecisionTime): boolean {
+ if (this.base < other.base) {
+ return true;
+ } else if (this.base === other.base) {
+ return this.offset < other.offset;
+ } else {
+ return false;
+ }
+ }
+
+ isLessThanOrEqual(other: HighPrecisionTime): boolean {
+ if (this.equals(other)) {
+ return true;
+ } else {
+ return this.isLessThan(other);
+ }
+ }
+
+ isGreaterThan(other: HighPrecisionTime): boolean {
+ return !this.isLessThanOrEqual(other);
+ }
+
+ isGreaterThanOrEqual(other: HighPrecisionTime): boolean {
+ return !this.isLessThan(other);
+ }
+
+ clamp(lower: HighPrecisionTime, upper: HighPrecisionTime): HighPrecisionTime {
+ if (this.isLessThan(lower)) {
+ return lower;
+ } else if (this.isGreaterThan(upper)) {
+ return upper;
+ } else {
+ return this;
+ }
+ }
+
+ toString(): string {
+ const offsetAsString = this.offset.toString();
+ if (offsetAsString === '0') {
+ return this.base.toString();
+ } else {
+ return `${this.base}${offsetAsString.substring(1)}`;
+ }
+ }
+}
+
+export class HighPrecisionTimeSpan implements Span<HighPrecisionTime> {
+ readonly start: HighPrecisionTime;
+ readonly end: HighPrecisionTime;
+
+ constructor(start: TPTime|HighPrecisionTime, end: TPTime|HighPrecisionTime) {
+ this.start = (start instanceof HighPrecisionTime) ?
+ start :
+ HighPrecisionTime.fromTPTime(start);
+ this.end = (end instanceof HighPrecisionTime) ?
+ end :
+ HighPrecisionTime.fromTPTime(end);
+ assertTrue(
+ this.start.isLessThanOrEqual(this.end),
+ `TimeSpan start [${this.start}] cannot be greater than end [${
+ this.end}]`);
+ }
+
+ static fromTpTime(start: TPTime, end: TPTime): HighPrecisionTimeSpan {
+ return new HighPrecisionTimeSpan(
+ HighPrecisionTime.fromTPTime(start),
+ HighPrecisionTime.fromTPTime(end),
+ );
+ }
+
+ static get ZERO(): HighPrecisionTimeSpan {
+ return new HighPrecisionTimeSpan(
+ HighPrecisionTime.ZERO,
+ HighPrecisionTime.ZERO,
+ );
+ }
+
+ get duration(): HighPrecisionTime {
+ return this.end.subtract(this.start);
+ }
+
+ get midpoint(): HighPrecisionTime {
+ return this.start.add(this.end).divide(2);
+ }
+
+ equals(other: Span<HighPrecisionTime>): boolean {
+ return this.start.equals(other.start) && this.end.equals(other.end);
+ }
+
+ contains(x: HighPrecisionTime|Span<HighPrecisionTime>): boolean {
+ if (x instanceof HighPrecisionTime) {
+ return this.start.isLessThanOrEqual(x) && x.isLessThan(this.end);
+ } else {
+ return this.start.isLessThanOrEqual(x.start) &&
+ x.end.isLessThanOrEqual(this.end);
+ }
+ }
+
+ intersects(x: Span<HighPrecisionTime>): boolean {
+ return !(
+ x.end.isLessThanOrEqual(this.start) ||
+ x.start.isGreaterThanOrEqual(this.end));
+ }
+
+ add(time: HighPrecisionTime): Span<HighPrecisionTime> {
+ return new HighPrecisionTimeSpan(this.start.add(time), this.end.add(time));
+ }
+
+ // Move the start and end away from each other a certain amount
+ pad(time: HighPrecisionTime): Span<HighPrecisionTime> {
+ return new HighPrecisionTimeSpan(
+ this.start.subtract(time),
+ this.end.add(time),
+ );
+ }
+}
diff --git a/ui/src/common/high_precision_time_unittest.ts b/ui/src/common/high_precision_time_unittest.ts
new file mode 100644
index 0000000..c3a2033
--- /dev/null
+++ b/ui/src/common/high_precision_time_unittest.ts
@@ -0,0 +1,308 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {
+ HighPrecisionTime as HPTime,
+ HighPrecisionTimeSpan as HPTimeSpan,
+} from './high_precision_time';
+import {TPTime} from './time';
+
+// Quick 'n' dirty function to convert a string to a HPtime
+// Used to make tests more readable
+// E.g. '1.3' -> {base: 1, offset: 0.3}
+// E.g. '-0.3' -> {base: -1, offset: 0.7}
+function mkTime(time: string): HPTime {
+ const array = time.split('.');
+ if (array.length > 2) throw new Error(`Bad time format ${time}`);
+ const [base, fractions] = array;
+ const negative = time.startsWith('-');
+ const numBase = BigInt(base);
+
+ if (fractions) {
+ const numFractions = Number(`0.${fractions}`);
+ if (negative) {
+ return new HPTime(numBase - 1n, 1.0 - numFractions);
+ } else {
+ return new HPTime(numBase, numFractions);
+ }
+ } else {
+ return new HPTime(numBase);
+ }
+}
+
+function mkSpan(t1: string, t2: string): HPTimeSpan {
+ return new HPTimeSpan(mkTime(t1), mkTime(t2));
+}
+
+describe('Time', () => {
+ it('should create a new Time object with the given base and offset', () => {
+ const time = new HPTime(136n, 0.3);
+ expect(time.base).toBe(136n);
+ expect(time.offset).toBeCloseTo(0.3);
+ });
+
+ it('should normalize when offset is >= 1', () => {
+ let time = new HPTime(1n, 2.3);
+ expect(time.base).toBe(3n);
+ expect(time.offset).toBeCloseTo(0.3);
+
+ time = new HPTime(1n, 1);
+ expect(time.base).toBe(2n);
+ expect(time.offset).toBeCloseTo(0);
+ });
+
+ it('should normalize when offset is < 0', () => {
+ const time = new HPTime(1n, -0.4);
+ expect(time.base).toBe(0n);
+ expect(time.offset).toBeCloseTo(0.6);
+ });
+
+ it('should store timestamps without losing precision', () => {
+ let time = HPTime.fromTPTime(123n as TPTime);
+ expect(time.toTPTime()).toBe(123n as TPTime);
+
+ time = HPTime.fromTPTime(1152921504606846976n as TPTime);
+ expect(time.toTPTime()).toBe(1152921504606846976n as TPTime);
+ });
+
+ it('should store and manipulate timestamps without losing precision', () => {
+ let time = HPTime.fromTPTime(123n as TPTime);
+ time = time.addTPTime(456n);
+ expect(time.toTPTime()).toBe(579n);
+
+ time = HPTime.fromTPTime(2315700508990407843n as TPTime);
+ time = time.addTPTime(2315718101717517451n as TPTime);
+ expect(time.toTPTime()).toBe(4631418610707925294n);
+ });
+
+ it('should add time', () => {
+ const time1 = mkTime('1.3');
+ const time2 = mkTime('3.1');
+ const result = time1.add(time2);
+ expect(result.base).toEqual(4n);
+ expect(result.offset).toBeCloseTo(0.4);
+ });
+
+ it('should subtract time', () => {
+ const time1 = mkTime('3.1');
+ const time2 = mkTime('1.3');
+ const result = time1.subtract(time2);
+ expect(result.base).toEqual(1n);
+ expect(result.offset).toBeCloseTo(0.8);
+ });
+
+ it('should add nanoseconds', () => {
+ const time = mkTime('1.3');
+ const result = time.addNanos(0.8);
+ expect(result.base).toEqual(2n);
+ expect(result.offset).toBeCloseTo(0.1);
+ });
+
+ it('should add seconds', () => {
+ const time = mkTime('1.3');
+ const result = time.addSeconds(0.008);
+ expect(result.base).toEqual(8000001n);
+ expect(result.offset).toBeCloseTo(0.3);
+ });
+
+ it('should perform gt comparisions', () => {
+ const time = mkTime('1.2');
+ expect(time.isGreaterThanOrEqual(mkTime('0.5'))).toBeTruthy();
+ expect(time.isGreaterThanOrEqual(mkTime('1.1'))).toBeTruthy();
+ expect(time.isGreaterThanOrEqual(mkTime('1.2'))).toBeTruthy();
+ expect(time.isGreaterThanOrEqual(mkTime('1.5'))).toBeFalsy();
+ expect(time.isGreaterThanOrEqual(mkTime('5.5'))).toBeFalsy();
+ });
+
+ it('should perform gte comparisions', () => {
+ const time = mkTime('1.2');
+ expect(time.isGreaterThan(mkTime('0.5'))).toBeTruthy();
+ expect(time.isGreaterThan(mkTime('1.1'))).toBeTruthy();
+ expect(time.isGreaterThan(mkTime('1.2'))).toBeFalsy();
+ expect(time.isGreaterThan(mkTime('1.5'))).toBeFalsy();
+ expect(time.isGreaterThan(mkTime('5.5'))).toBeFalsy();
+ });
+
+ it('should perform lt comparisions', () => {
+ const time = mkTime('1.2');
+ expect(time.isLessThan(mkTime('0.5'))).toBeFalsy();
+ expect(time.isLessThan(mkTime('1.1'))).toBeFalsy();
+ expect(time.isLessThan(mkTime('1.2'))).toBeFalsy();
+ expect(time.isLessThan(mkTime('1.5'))).toBeTruthy();
+ expect(time.isLessThan(mkTime('5.5'))).toBeTruthy();
+ });
+
+ it('should perform lte comparisions', () => {
+ const time = mkTime('1.2');
+ expect(time.isLessThanOrEqual(mkTime('0.5'))).toBeFalsy();
+ expect(time.isLessThanOrEqual(mkTime('1.1'))).toBeFalsy();
+ expect(time.isLessThanOrEqual(mkTime('1.2'))).toBeTruthy();
+ expect(time.isLessThanOrEqual(mkTime('1.5'))).toBeTruthy();
+ expect(time.isLessThanOrEqual(mkTime('5.5'))).toBeTruthy();
+ });
+
+ it('should detect equality', () => {
+ const time = new HPTime(1n, 0.2);
+ expect(time.equals(new HPTime(1n, 0.2))).toBeTruthy();
+ expect(time.equals(new HPTime(0n, 1.2))).toBeTruthy();
+ expect(time.equals(new HPTime(-100n, 101.2))).toBeTruthy();
+ expect(time.equals(new HPTime(1n, 0.3))).toBeFalsy();
+ expect(time.equals(new HPTime(2n, 0.2))).toBeFalsy();
+ });
+
+ it('should clamp a time to a range', () => {
+ const time1 = mkTime('1.2');
+ const time2 = mkTime('5.4');
+ const time3 = mkTime('2.8');
+ const lower = mkTime('2.3');
+ const upper = mkTime('4.5');
+ expect(time1.clamp(lower, upper)).toEqual(lower);
+ expect(time2.clamp(lower, upper)).toEqual(upper);
+ expect(time3.clamp(lower, upper)).toEqual(time3);
+ });
+
+ it('should convert to seconds', () => {
+ expect(new HPTime(1n, .2).seconds).toBeCloseTo(0.0000000012);
+ expect(new HPTime(1000000000n, .0).seconds).toBeCloseTo(1);
+ });
+
+ it('should convert to nanos', () => {
+ expect(new HPTime(1n, .2).nanos).toBeCloseTo(1.2);
+ expect(new HPTime(1000000000n, .0).nanos).toBeCloseTo(1e9);
+ });
+
+ it('should convert to timestamps', () => {
+ expect(new HPTime(1n, .2).toTPTime('round')).toBe(1n);
+ expect(new HPTime(1n, .5).toTPTime('round')).toBe(2n);
+ expect(new HPTime(1n, .2).toTPTime('floor')).toBe(1n);
+ expect(new HPTime(1n, .5).toTPTime('floor')).toBe(1n);
+ expect(new HPTime(1n, .2).toTPTime('ceil')).toBe(2n);
+ expect(new HPTime(1n, .5).toTPTime('ceil')).toBe(2n);
+ });
+
+ it('should divide', () => {
+ let result = mkTime('1').divide(2);
+ expect(result.base).toBe(0n);
+ expect(result.offset).toBeCloseTo(0.5);
+
+ result = mkTime('1.6').divide(2);
+ expect(result.base).toBe(0n);
+ expect(result.offset).toBeCloseTo(0.8);
+
+ result = mkTime('-0.5').divide(2);
+ expect(result.base).toBe(-1n);
+ expect(result.offset).toBeCloseTo(0.75);
+
+ result = mkTime('123.1').divide(123);
+ expect(result.base).toBe(1n);
+ expect(result.offset).toBeCloseTo(0.000813, 6);
+ });
+
+ it('should multiply', () => {
+ let result = mkTime('1').multiply(2);
+ expect(result.base).toBe(2n);
+ expect(result.offset).toBeCloseTo(0);
+
+ result = mkTime('1').multiply(2.5);
+ expect(result.base).toBe(2n);
+ expect(result.offset).toBeCloseTo(0.5);
+
+ result = mkTime('-0.5').multiply(2);
+ expect(result.base).toBe(-1n);
+ expect(result.offset).toBeCloseTo(0.0);
+
+ result = mkTime('123.1').multiply(25.5);
+ expect(result.base).toBe(3139n);
+ expect(result.offset).toBeCloseTo(0.05);
+ });
+
+ it('should convert to string', () => {
+ expect(mkTime('1.3').toString()).toBe('1.3');
+ expect(mkTime('12983423847.332533').toString()).toBe('12983423847.332533');
+ expect(new HPTime(234n).toString()).toBe('234');
+ });
+});
+
+describe('HighPrecisionTimeSpan', () => {
+ it('can be constructed from HP time', () => {
+ const span = new HPTimeSpan(mkTime('10'), mkTime('20'));
+ expect(span.start).toEqual(mkTime('10'));
+ expect(span.end).toEqual(mkTime('20'));
+ });
+
+ it('can be constructed from integer time', () => {
+ const span = new HPTimeSpan(10n, 20n);
+ expect(span.start).toEqual(mkTime('10'));
+ expect(span.end).toEqual(mkTime('20'));
+ });
+
+ it('throws when start is later than end', () => {
+ expect(() => new HPTimeSpan(mkTime('0.1'), mkTime('0'))).toThrow();
+ expect(() => new HPTimeSpan(mkTime('1124.0001'), mkTime('1124'))).toThrow();
+ });
+
+ it('can calc duration', () => {
+ let dur = mkSpan('10', '20').duration;
+ expect(dur.base).toBe(10n);
+ expect(dur.offset).toBeCloseTo(0);
+
+ dur = mkSpan('10.123', '20.456').duration;
+ expect(dur.base).toBe(10n);
+ expect(dur.offset).toBeCloseTo(0.333);
+ });
+
+ it('can calc midpoint', () => {
+ let mid = mkSpan('10', '20').midpoint;
+ expect(mid.base).toBe(15n);
+ expect(mid.offset).toBeCloseTo(0);
+
+ mid = mkSpan('10.25', '16.75').midpoint;
+ expect(mid.base).toBe(13n);
+ expect(mid.offset).toBeCloseTo(0.5);
+ });
+
+ it('can be compared', () => {
+ expect(mkSpan('0.1', '34.2').equals(mkSpan('0.1', '34.2'))).toBeTruthy();
+ expect(mkSpan('0.1', '34.5').equals(mkSpan('0.1', '34.2'))).toBeFalsy();
+ expect(mkSpan('0.9', '34.2').equals(mkSpan('0.1', '34.2'))).toBeFalsy();
+ });
+
+ it('checks if span contains another span', () => {
+ const x = mkSpan('10', '20');
+
+ expect(x.contains(mkTime('9'))).toBeFalsy();
+ expect(x.contains(mkTime('10'))).toBeTruthy();
+ expect(x.contains(mkTime('15'))).toBeTruthy();
+ expect(x.contains(mkTime('20'))).toBeFalsy();
+ expect(x.contains(mkTime('21'))).toBeFalsy();
+
+ expect(x.contains(mkSpan('12', '18'))).toBeTruthy();
+ expect(x.contains(mkSpan('5', '25'))).toBeFalsy();
+ expect(x.contains(mkSpan('5', '15'))).toBeFalsy();
+ expect(x.contains(mkSpan('15', '25'))).toBeFalsy();
+ expect(x.contains(mkSpan('0', '10'))).toBeFalsy();
+ expect(x.contains(mkSpan('20', '30'))).toBeFalsy();
+ });
+
+ it('checks if span intersects another span', () => {
+ const x = mkSpan('10', '20');
+
+ expect(x.intersects(mkSpan('0', '10'))).toBeFalsy();
+ expect(x.intersects(mkSpan('5', '15'))).toBeTruthy();
+ expect(x.intersects(mkSpan('12', '18'))).toBeTruthy();
+ expect(x.intersects(mkSpan('15', '25'))).toBeTruthy();
+ expect(x.intersects(mkSpan('20', '30'))).toBeFalsy();
+ expect(x.intersects(mkSpan('5', '25'))).toBeTruthy();
+ });
+});
diff --git a/ui/src/common/internal_layout_utils.ts b/ui/src/common/internal_layout_utils.ts
new file mode 100644
index 0000000..478cd02
--- /dev/null
+++ b/ui/src/common/internal_layout_utils.ts
@@ -0,0 +1,50 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Object to facilitate generation of SELECT statement using
+// generateSqlWithInternalLayout.
+//
+// Fields:
+// @columns: a string array list of the columns to be selected from the table.
+// @layoutParams: a config of the timestamp (ts) and duration (dur) fields
+// required by the internal_layout function.
+// @sourceTable: the table in the FROM clause, source of the data.
+// @whereClause: the WHERE clause to filter data from the source table.
+// @orderByClause: the ORDER BY clause for the query data.
+interface GenerateSqlArgs {
+ columns: string[];
+ layoutParams: {ts: string, dur: string};
+ sourceTable: string;
+ whereClause?: string;
+ orderByClause?: string;
+}
+
+// Function to generate a SELECT statement utilizing the internal_layout
+// SQL function as a depth field.
+export function generateSqlWithInternalLayout(sqlArgs: GenerateSqlArgs):
+ string {
+ let sql = `SELECT ` + sqlArgs.columns.toString() + ', internal_layout(' +
+ sqlArgs.layoutParams.ts + ',' + sqlArgs.layoutParams.dur +
+ ') OVER (ORDER BY ' + sqlArgs.layoutParams.ts +
+ ' ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS depth' +
+ ' FROM ' + sqlArgs.sourceTable;
+ if (sqlArgs.whereClause !== undefined) {
+ sql += ' WHERE ' + sqlArgs.whereClause;
+ }
+ if (sqlArgs.orderByClause !== undefined) {
+ sql += ' ORDER BY ' + sqlArgs.orderByClause;
+ }
+ sql += ';';
+ return sql;
+}
diff --git a/ui/src/common/logs.ts b/ui/src/common/logs.ts
index 0fc2fae..04cf065 100644
--- a/ui/src/common/logs.ts
+++ b/ui/src/common/logs.ts
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {TPTime} from './time';
+
export const LogExistsKey = 'log-exists';
export const LogBoundsKey = 'log-bounds';
export const LogEntriesKey = 'log-entries';
@@ -19,16 +21,16 @@
export interface LogExists { exists: boolean; }
export interface LogBounds {
- startTs: number;
- endTs: number;
- firstRowTs: number;
- lastRowTs: number;
- total: number;
+ firstLogTs: TPTime;
+ lastLogTs: TPTime;
+ firstVisibleLogTs: TPTime;
+ lastVisibleLogTs: TPTime;
+ totalVisibleLogs: number;
}
export interface LogEntries {
offset: number;
- timestamps: number[];
+ timestamps: TPTime[];
priorities: number[];
tags: string[];
messages: string[];
diff --git a/ui/src/common/plugin_api.ts b/ui/src/common/plugin_api.ts
index fa8a9fc..0dc66d6 100644
--- a/ui/src/common/plugin_api.ts
+++ b/ui/src/common/plugin_api.ts
@@ -15,9 +15,12 @@
import {EngineProxy} from '../common/engine';
import {TrackControllerFactory} from '../controller/track_controller';
import {TrackCreator} from '../frontend/track';
+import {Selection} from './state';
export {EngineProxy} from '../common/engine';
export {
+ LONG,
+ LONG_NULL,
NUM,
NUM_NULL,
STR,
@@ -66,6 +69,16 @@
// could be registered in dev.perfetto.CounterTrack - a whole
// different plugin.
registerTrack(track: TrackCreator): void;
+
+ // Register custom functionality to specify how the plugin should handle
+ // selection changes for tracks in this plugin.
+ //
+ // Params:
+ // @onDetailsPanelSelectionChange a function that takes a Selection as its
+ // parameter and performs whatever must happen on the details panel when the
+ // selection is invoked.
+ registerOnDetailsPanelSelectionChange(
+ onDetailsPanelSelectionChange: (newSelection?: Selection) => void): void;
}
export interface PluginInfo {
diff --git a/ui/src/common/plugins.ts b/ui/src/common/plugins.ts
index aa414bc..5898c5f 100644
--- a/ui/src/common/plugins.ts
+++ b/ui/src/common/plugins.ts
@@ -27,12 +27,14 @@
TrackProvider,
} from './plugin_api';
import {Registry} from './registry';
+import {Selection} from './state';
// Every plugin gets its own PluginContext. This is how we keep track
// what each plugin is doing and how we can blame issues on particular
// plugins.
export class PluginContextImpl implements PluginContext {
readonly pluginId: string;
+ onDetailsPanelSelectionChange?: (newSelection?: Selection) => void;
private trackProviders: TrackProvider[];
constructor(pluginId: string) {
@@ -53,6 +55,11 @@
registerTrackProvider(provider: TrackProvider) {
this.trackProviders.push(provider);
}
+
+ registerOnDetailsPanelSelectionChange(
+ onDetailsPanelSelectionChange: (newSelection?: Selection) => void) {
+ this.onDetailsPanelSelectionChange = onDetailsPanelSelectionChange;
+ }
// ==================================================================
// ==================================================================
@@ -123,6 +130,14 @@
}
return promises;
}
+
+ onDetailsPanelSelectionChange(pluginId: string, newSelection?: Selection) {
+ const pluginContext = this.getPluginContext(pluginId);
+ if (pluginContext === undefined) return;
+ if (pluginContext.onDetailsPanelSelectionChange) {
+ pluginContext.onDetailsPanelSelectionChange(newSelection);
+ }
+ }
}
// TODO(hjd): Sort out the story for global singletons like these:
diff --git a/ui/src/common/query_result.ts b/ui/src/common/query_result.ts
index e8d482d..90fb8f4 100644
--- a/ui/src/common/query_result.ts
+++ b/ui/src/common/query_result.ts
@@ -159,7 +159,7 @@
// One row extracted from an SQL result:
export interface Row {
- [key: string]: ColumnType;
+ [key: string]: ColumnType|undefined;
}
// The methods that any iterator has to implement.
diff --git a/ui/src/common/recordingV2/recording_config_utils.ts b/ui/src/common/recordingV2/recording_config_utils.ts
index 2840b3c..d02da5a 100644
--- a/ui/src/common/recordingV2/recording_config_utils.ts
+++ b/ui/src/common/recordingV2/recording_config_utils.ts
@@ -79,9 +79,8 @@
export function genTraceConfig(
uiCfg: RecordConfig, targetInfo: TargetInfo): TraceConfig {
- const androidApiLevel = (targetInfo.targetType === 'ANDROID') ?
- targetInfo.androidApiLevel :
- undefined;
+ const isAndroid = targetInfo.targetType === 'ANDROID';
+ const androidApiLevel = isAndroid ? targetInfo.androidApiLevel : undefined;
const protoCfg = new TraceConfig();
protoCfg.durationMs = uiCfg.durationMs;
@@ -96,8 +95,8 @@
protoCfg.buffers.push(new BufferConfig());
protoCfg.buffers.push(new BufferConfig());
- protoCfg.buffers[1].sizeKb = slowBufSizeKb;
protoCfg.buffers[0].sizeKb = fastBufSizeKb;
+ protoCfg.buffers[1].sizeKb = slowBufSizeKb;
if (uiCfg.mode === 'STOP_WHEN_FULL') {
protoCfg.buffers[0].fillPolicy = BufferConfig.FillPolicy.DISCARD;
@@ -131,6 +130,14 @@
let procThreadAssociationFtrace = false;
let trackInitialOomScore = false;
+ if (isAndroid) {
+ const ds = new TraceConfig.DataSource();
+ ds.config = new DataSourceConfig();
+ ds.config.targetBuffer = 1;
+ ds.config.name = 'android.packages_list';
+ protoCfg.dataSources.push(ds);
+ }
+
if (uiCfg.cpuSched) {
procThreadAssociationPolling = true;
procThreadAssociationFtrace = true;
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index d4d07b7..91ca358 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -18,7 +18,10 @@
PivotTree,
TableColumn,
} from '../frontend/pivot_table_types';
+import {TopLevelScrollSelection} from '../tracks/scroll_jank/scroll_track';
+
import {Direction} from './event_set';
+import {TPDuration, TPTime} from './time';
/**
* A plain js object, holding objects of type |Class| keyed by string id.
@@ -39,9 +42,9 @@
}
export interface VisibleState extends Timestamped {
- startSec: number;
- endSec: number;
- resolution: number;
+ start: TPTime;
+ end: TPTime;
+ resolution: TPDuration;
}
export interface AreaSelection {
@@ -59,8 +62,8 @@
export type AreaById = Area&{id: string};
export interface Area {
- startSec: number;
- endSec: number;
+ start: TPTime;
+ end: TPTime;
tracks: string[];
}
@@ -100,7 +103,8 @@
// 28. Add a boolean indicating if non matching log entries are hidden.
// 29. Add ftrace state. <-- Borked, state contains a non-serializable object.
// 30. Convert ftraceFilter.excludedNames from Set<string> to string[].
-export const STATE_VERSION = 30;
+// 31. Convert all timestamps to bigints.
+export const STATE_VERSION = 31;
export const SCROLLING_TRACK_GROUP = 'ScrollingTracks';
@@ -268,8 +272,8 @@
}
export interface TraceTime {
- startSec: number;
- endSec: number;
+ start: TPTime;
+ end: TPTime;
}
export interface FrontendLocalState {
@@ -284,7 +288,7 @@
export interface Note {
noteType: 'DEFAULT';
id: string;
- timestamp: number;
+ timestamp: TPTime;
color: string;
text: string;
}
@@ -311,14 +315,14 @@
kind: 'DEBUG_SLICE';
id: number;
sqlTableName: string;
- startS: number;
- durationS: number;
+ start: TPTime;
+ duration: TPDuration;
}
export interface CounterSelection {
kind: 'COUNTER';
- leftTs: number;
- rightTs: number;
+ leftTs: TPTime;
+ rightTs: TPTime;
id: number;
}
@@ -326,7 +330,7 @@
kind: 'HEAP_PROFILE';
id: number;
upid: number;
- ts: number;
+ ts: TPTime;
type: ProfileType;
}
@@ -334,16 +338,16 @@
kind: 'PERF_SAMPLES';
id: number;
upid: number;
- leftTs: number;
- rightTs: number;
+ leftTs: TPTime;
+ rightTs: TPTime;
type: ProfileType;
}
export interface FlamegraphState {
kind: 'FLAMEGRAPH_STATE';
upids: number[];
- startNs: number;
- endNs: number;
+ start: TPTime;
+ end: TPTime;
type: ProfileType;
viewingOption: FlamegraphStateViewingOption;
focusRegex: string;
@@ -377,8 +381,8 @@
export type Selection =
(NoteSelection|SliceSelection|CounterSelection|HeapProfileSelection|
CpuProfileSampleSelection|ChromeSliceSelection|ThreadStateSelection|
- AreaSelection|PerfSamplesSelection|LogSelection|DebugSliceSelection)&
- {trackId?: string};
+ AreaSelection|PerfSamplesSelection|LogSelection|DebugSliceSelection|
+ TopLevelScrollSelection)&{trackId?: string};
export type SelectionKind = Selection['kind']; // 'THREAD_STATE' | 'SLICE' ...
export interface Pagination {
@@ -570,8 +574,8 @@
// Hovered and focused events
hoveredUtid: number;
hoveredPid: number;
- hoverCursorTimestamp: number;
- hoveredNoteTimestamp: number;
+ hoverCursorTimestamp: TPTime;
+ hoveredNoteTimestamp: TPTime;
highlightedSliceId: number;
focusedFlowIdLeft: number;
focusedFlowIdRight: number;
@@ -608,8 +612,8 @@
}
export const defaultTraceTime = {
- startSec: 0,
- endSec: 10,
+ start: 0n,
+ end: BigInt(10e9),
};
export declare type RecordMode =
diff --git a/ui/src/common/time.ts b/ui/src/common/time.ts
index ea5e9d8..5608d3f 100644
--- a/ui/src/common/time.ts
+++ b/ui/src/common/time.ts
@@ -13,8 +13,7 @@
// limitations under the License.
import {assertTrue} from '../base/logging';
-
-const EPSILON = 0.0000000001;
+import {ColumnType} from './query_result';
// TODO(hjd): Combine with timeToCode.
export function timeToString(sec: number) {
@@ -29,6 +28,10 @@
return `${sign < 0 ? '-' : ''}${Math.round(n * 10) / 10} ${units[u]}`;
}
+export function tpTimeToString(time: TPTime) {
+ return timeToString(tpTimeToSeconds(time));
+}
+
export function fromNs(ns: number) {
return ns / 1e9;
}
@@ -52,6 +55,10 @@
return parts.join('.');
}
+export function formatTPTime(time: TPTime) {
+ return formatTimestamp(tpTimeToSeconds(time));
+}
+
// TODO(hjd): Rename to formatTimestampWithUnits
// 1000000023ns -> "1s 23ns"
export function timeToCode(sec: number): string {
@@ -77,44 +84,128 @@
return result.slice(0, -1);
}
+export function tpTimeToCode(time: TPTime) {
+ return timeToCode(tpTimeToSeconds(time));
+}
+
export function currentDateHourAndMinute(): string {
const date = new Date();
return `${date.toISOString().substr(0, 10)}-${date.getHours()}-${
date.getMinutes()}`;
}
-export class TimeSpan {
- readonly start: number;
- readonly end: number;
+// Aliased "Trace Processor" time and duration types.
+// Note(stevegolton): While it might be nice to type brand these in the future,
+// for now we're going to keep things simple. We do a lot of maths with these
+// timestamps and type branding requires a lot of jumping through hoops to
+// coerse the type back to the correct format.
+export type TPTime = bigint;
+export type TPDuration = bigint;
- constructor(start: number, end: number) {
- assertTrue(start <= end);
+export function tpTimeFromNanos(nanos: number): TPTime {
+ return BigInt(Math.floor(nanos));
+}
+
+export function tpTimeFromSeconds(seconds: number): TPTime {
+ return BigInt(Math.floor(seconds * 1e9));
+}
+
+export function tpTimeToNanos(time: TPTime): number {
+ return Number(time);
+}
+
+export function tpTimeToMillis(time: TPTime): number {
+ return Number(time) / 1e6;
+}
+
+export function tpTimeToSeconds(time: TPTime): number {
+ return Number(time) / 1e9;
+}
+
+// Create a TPTime from an arbitrary SQL value.
+// Throws if the value cannot be reasonably converted to a bigint.
+// Assumes value is in nanoseconds.
+export function tpTimeFromSql(value: ColumnType): TPTime {
+ if (typeof value === 'bigint') {
+ return value;
+ } else if (typeof value === 'number') {
+ return tpTimeFromNanos(value);
+ } else if (value === null) {
+ return 0n;
+ } else {
+ throw Error(`Refusing to create Timestamp from unrelated type ${value}`);
+ }
+}
+
+export function tpDurationToSeconds(dur: TPDuration): number {
+ return tpTimeToSeconds(dur);
+}
+
+export function tpDurationToNanos(dur: TPDuration): number {
+ return tpTimeToSeconds(dur);
+}
+
+export function tpDurationFromNanos(nanos: number): TPDuration {
+ return tpTimeFromNanos(nanos);
+}
+
+export function tpDurationFromSql(nanos: ColumnType): TPDuration {
+ return tpTimeFromSql(nanos);
+}
+
+export interface Span<Unit, Duration = Unit> {
+ get start(): Unit;
+ get end(): Unit;
+ get duration(): Duration;
+ get midpoint(): Unit;
+ contains(span: Unit|Span<Unit, Duration>): boolean;
+ intersects(x: Span<Unit>): boolean;
+ equals(span: Span<Unit, Duration>): boolean;
+ add(offset: Duration): Span<Unit, Duration>;
+ pad(padding: Duration): Span<Unit, Duration>;
+}
+
+export class TPTimeSpan implements Span<TPTime, TPDuration> {
+ readonly start: TPTime;
+ readonly end: TPTime;
+
+ constructor(start: TPTime, end: TPTime) {
+ assertTrue(
+ start <= end,
+ `Span start [${start}] cannot be greater than end [${end}]`);
this.start = start;
this.end = end;
}
- clone() {
- return new TimeSpan(this.start, this.end);
- }
-
- equals(other: TimeSpan): boolean {
- return Math.abs(this.start - other.start) < EPSILON &&
- Math.abs(this.end - other.end) < EPSILON;
- }
-
- get duration() {
+ get duration(): TPDuration {
return this.end - this.start;
}
- isInBounds(sec: number) {
- return this.start <= sec && sec <= this.end;
+ get midpoint(): TPTime {
+ return (this.start + this.end) / 2n;
}
- add(sec: number): TimeSpan {
- return new TimeSpan(this.start + sec, this.end + sec);
+ contains(x: TPTime|Span<TPTime, TPDuration>): boolean {
+ if (typeof x === 'bigint') {
+ return this.start <= x && x < this.end;
+ } else {
+ return this.start <= x.start && x.end <= this.end;
+ }
}
- contains(other: TimeSpan) {
- return this.start <= other.start && other.end <= this.end;
+ intersects(x: Span<TPTime, TPDuration>): boolean {
+ return !(x.end <= this.start || x.start >= this.end);
+ }
+
+ equals(span: Span<TPTime, TPDuration>): boolean {
+ return this.start === span.start && this.end === span.end;
+ }
+
+ add(x: TPTime): Span<TPTime, TPDuration> {
+ return new TPTimeSpan(this.start + x, this.end + x);
+ }
+
+ pad(padding: TPDuration): Span<TPTime, TPDuration> {
+ return new TPTimeSpan(this.start - padding, this.end + padding);
}
}
diff --git a/ui/src/common/time_unittest.ts b/ui/src/common/time_unittest.ts
index 7bfead1..b9e6bd9 100644
--- a/ui/src/common/time_unittest.ts
+++ b/ui/src/common/time_unittest.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {TimeSpan, timeToCode} from './time';
+import {timeToCode, TPTime, TPTimeSpan} from './time';
test('seconds to code', () => {
expect(timeToCode(3)).toEqual('3s');
@@ -29,9 +29,67 @@
expect(timeToCode(0)).toEqual('0s');
});
-test('Time span equality', () => {
- expect((new TimeSpan(0, 1)).equals(new TimeSpan(0, 1))).toBe(true);
- expect((new TimeSpan(0, 1)).equals(new TimeSpan(0, 2))).toBe(false);
- expect((new TimeSpan(0, 1)).equals(new TimeSpan(0, 1 + Number.EPSILON)))
- .toBe(true);
+function mkSpan(start: TPTime, end: TPTime) {
+ return new TPTimeSpan(start, end);
+}
+
+describe('TPTimeSpan', () => {
+ it('throws when start is later than end', () => {
+ expect(() => mkSpan(1n, 0n)).toThrow();
+ });
+
+ it('can calc duration', () => {
+ expect(mkSpan(10n, 20n).duration).toBe(10n);
+ });
+
+ it('can calc midpoint', () => {
+ expect(mkSpan(10n, 20n).midpoint).toBe(15n);
+ expect(mkSpan(10n, 19n).midpoint).toBe(14n);
+ expect(mkSpan(10n, 10n).midpoint).toBe(10n);
+ });
+
+ it('can be compared', () => {
+ const x = mkSpan(10n, 20n);
+ expect(x.equals(mkSpan(10n, 20n))).toBeTruthy();
+ expect(x.equals(mkSpan(11n, 20n))).toBeFalsy();
+ expect(x.equals(mkSpan(10n, 19n))).toBeFalsy();
+ });
+
+ it('checks containment', () => {
+ const x = mkSpan(10n, 20n);
+
+ expect(x.contains(9n)).toBeFalsy();
+ expect(x.contains(10n)).toBeTruthy();
+ expect(x.contains(15n)).toBeTruthy();
+ expect(x.contains(20n)).toBeFalsy();
+ expect(x.contains(21n)).toBeFalsy();
+
+ expect(x.contains(mkSpan(12n, 18n))).toBeTruthy();
+ expect(x.contains(mkSpan(5n, 25n))).toBeFalsy();
+ expect(x.contains(mkSpan(5n, 15n))).toBeFalsy();
+ expect(x.contains(mkSpan(15n, 25n))).toBeFalsy();
+ expect(x.contains(mkSpan(0n, 10n))).toBeFalsy();
+ expect(x.contains(mkSpan(20n, 30n))).toBeFalsy();
+ });
+
+ it('checks intersection', () => {
+ const x = mkSpan(10n, 20n);
+
+ expect(x.intersects(mkSpan(0n, 10n))).toBeFalsy();
+ expect(x.intersects(mkSpan(5n, 15n))).toBeTruthy();
+ expect(x.intersects(mkSpan(12n, 18n))).toBeTruthy();
+ expect(x.intersects(mkSpan(15n, 25n))).toBeTruthy();
+ expect(x.intersects(mkSpan(20n, 30n))).toBeFalsy();
+ expect(x.intersects(mkSpan(5n, 25n))).toBeTruthy();
+ });
+
+ it('can add', () => {
+ const x = mkSpan(10n, 20n);
+ expect(x.add(5n)).toEqual(mkSpan(15n, 25n));
+ });
+
+ it('can pad', () => {
+ const x = mkSpan(10n, 20n);
+ expect(x.pad(5n)).toEqual(mkSpan(5n, 25n));
+ });
});
diff --git a/ui/src/common/track_data.ts b/ui/src/common/track_data.ts
index 9af7fff..a49a56d 100644
--- a/ui/src/common/track_data.ts
+++ b/ui/src/common/track_data.ts
@@ -12,12 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {TPDuration, TPTime} from './time';
+
// TODO(hjd): Refactor into method on TrackController
export const LIMIT = 10000;
export interface TrackData {
- start: number;
- end: number;
- resolution: number;
+ start: TPTime;
+ end: TPTime;
+ resolution: TPDuration;
length: number;
}
diff --git a/ui/src/controller/aggregation/counter_aggregation_controller.ts b/ui/src/controller/aggregation/counter_aggregation_controller.ts
index dd7f14a..e632f8e 100644
--- a/ui/src/controller/aggregation/counter_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/counter_aggregation_controller.ts
@@ -15,7 +15,7 @@
import {ColumnDef} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
import {Area, Sorting} from '../../common/state';
-import {toNs} from '../../common/time';
+import {tpDurationToSeconds} from '../../common/time';
import {globals} from '../../frontend/globals';
import {Config, COUNTER_TRACK_KIND} from '../../tracks/counter';
@@ -38,21 +38,22 @@
}
}
if (ids.length === 0) return false;
+ const duration = area.end - area.start;
+ const durationSec = tpDurationToSeconds(duration);
const query = `create view ${this.kind} as select
name,
count(1) as count,
- round(sum(weighted_value)/${
- toNs(area.endSec) - toNs(area.startSec)}, 2) as avg_value,
+ round(sum(weighted_value)/${duration}, 2) as avg_value,
last as last_value,
first as first_value,
max(last) - min(first) as delta_value,
- round((max(last) - min(first))/${area.endSec - area.startSec}, 2) as rate,
+ round((max(last) - min(first))/${durationSec}, 2) as rate,
min(value) as min_value,
max(value) as max_value
from
(select *,
- (min(ts + dur, ${toNs(area.endSec)}) - max(ts,${toNs(area.startSec)}))
+ (min(ts + dur, ${area.end}) - max(ts,${area.start}))
* value as weighted_value,
first_value(value) over
(partition by track_id order by ts) as first,
@@ -61,8 +62,8 @@
range between unbounded preceding and unbounded following) as last
from experimental_counter_dur
where track_id in (${ids})
- and ts + dur >= ${toNs(area.startSec)} and
- ts <= ${toNs(area.endSec)})
+ and ts + dur >= ${area.start} and
+ ts <= ${area.end})
join counter_track
on track_id = counter_track.id
group by track_id`;
diff --git a/ui/src/controller/aggregation/cpu_aggregation_controller.ts b/ui/src/controller/aggregation/cpu_aggregation_controller.ts
index 94d3950..452ca75 100644
--- a/ui/src/controller/aggregation/cpu_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/cpu_aggregation_controller.ts
@@ -15,7 +15,6 @@
import {ColumnDef} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
import {Area, Sorting} from '../../common/state';
-import {toNs} from '../../common/time';
import {globals} from '../../frontend/globals';
import {Config, CPU_SLICE_TRACK_KIND} from '../../tracks/cpu_slices';
@@ -46,8 +45,8 @@
JOIN thread_state USING(utid)
WHERE cpu IN (${selectedCpus}) AND
state = "Running" AND
- thread_state.ts + thread_state.dur > ${toNs(area.startSec)} AND
- thread_state.ts < ${toNs(area.endSec)} group by utid`;
+ thread_state.ts + thread_state.dur > ${area.start} AND
+ thread_state.ts < ${area.end} group by utid`;
await engine.query(query);
return true;
diff --git a/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts b/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts
index b28e496..fc24d1e 100644
--- a/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts
@@ -15,7 +15,6 @@
import {ColumnDef} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
import {Area, Sorting} from '../../common/state';
-import {toNs} from '../../common/time';
import {globals} from '../../frontend/globals';
import {Config, CPU_SLICE_TRACK_KIND} from '../../tracks/cpu_slices';
@@ -45,8 +44,8 @@
JOIN thread_state USING(utid)
WHERE cpu IN (${selectedCpus}) AND
state = "Running" AND
- thread_state.ts + thread_state.dur > ${toNs(area.startSec)} AND
- thread_state.ts < ${toNs(area.endSec)} group by upid`;
+ thread_state.ts + thread_state.dur > ${area.start} AND
+ thread_state.ts < ${area.end} group by upid`;
await engine.query(query);
return true;
diff --git a/ui/src/controller/aggregation/frame_aggregation_controller.ts b/ui/src/controller/aggregation/frame_aggregation_controller.ts
index 97e1f86..a22a83d 100644
--- a/ui/src/controller/aggregation/frame_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/frame_aggregation_controller.ts
@@ -15,7 +15,6 @@
import {ColumnDef} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
import {Area, Sorting} from '../../common/state';
-import {toNs} from '../../common/time';
import {globals} from '../../frontend/globals';
import {
ACTUAL_FRAMES_SLICE_TRACK_KIND,
@@ -48,8 +47,8 @@
MAX(dur) as maxDur
FROM actual_frame_timeline_slice
WHERE track_id IN (${selectedSqlTrackIds}) AND
- ts + dur > ${toNs(area.startSec)} AND
- ts < ${toNs(area.endSec)} group by jank_type`;
+ ts + dur > ${area.start} AND
+ ts < ${area.end} group by jank_type`;
await engine.query(query);
return true;
diff --git a/ui/src/controller/aggregation/slice_aggregation_controller.ts b/ui/src/controller/aggregation/slice_aggregation_controller.ts
index ebb8000..8dcaccc 100644
--- a/ui/src/controller/aggregation/slice_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/slice_aggregation_controller.ts
@@ -15,7 +15,6 @@
import {ColumnDef} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
import {Area, Sorting} from '../../common/state';
-import {toNs} from '../../common/time';
import {globals} from '../../frontend/globals';
import {
ASYNC_SLICE_TRACK_KIND,
@@ -64,8 +63,8 @@
count(1) as occurrences
FROM slices
WHERE track_id IN (${selectedTrackIds}) AND
- ts + dur > ${toNs(area.startSec)} AND
- ts < ${toNs(area.endSec)} group by name`;
+ ts + dur > ${area.start} AND
+ ts < ${area.end} group by name`;
await engine.query(query);
return true;
diff --git a/ui/src/controller/aggregation/thread_aggregation_controller.ts b/ui/src/controller/aggregation/thread_aggregation_controller.ts
index ddfadae..6e288d5 100644
--- a/ui/src/controller/aggregation/thread_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/thread_aggregation_controller.ts
@@ -17,7 +17,6 @@
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';
import {globals} from '../../frontend/globals';
import {
Config,
@@ -60,8 +59,8 @@
JOIN thread USING(upid)
JOIN thread_state USING(utid)
WHERE utid IN (${this.utids}) AND
- thread_state.ts + thread_state.dur > ${toNs(area.startSec)} AND
- thread_state.ts < ${toNs(area.endSec)}
+ thread_state.ts + thread_state.dur > ${area.start} AND
+ thread_state.ts < ${area.end}
GROUP BY utid, concat_state
`;
@@ -78,8 +77,8 @@
JOIN thread USING(upid)
JOIN thread_state USING(utid)
WHERE utid IN (${this.utids}) AND thread_state.ts + thread_state.dur > ${
- toNs(area.startSec)} AND
- thread_state.ts < ${toNs(area.endSec)}
+ area.start} AND
+ thread_state.ts < ${area.end}
GROUP BY state, io_wait`;
const result = await engine.query(query);
diff --git a/ui/src/controller/area_selection_handler.ts b/ui/src/controller/area_selection_handler.ts
index b1d1c7e..32dcb11 100644
--- a/ui/src/controller/area_selection_handler.ts
+++ b/ui/src/controller/area_selection_handler.ts
@@ -36,10 +36,10 @@
// where `a ||= b` is formatted to `a || = b`, by inserting a space which
// breaks the operator.
// Therefore, we are using the pattern `a = a || b` instead.
- hasAreaChanged = hasAreaChanged ||
- selectedArea.startSec !== this.previousArea.startSec;
hasAreaChanged =
- hasAreaChanged || selectedArea.endSec !== this.previousArea.endSec;
+ hasAreaChanged || selectedArea.start !== this.previousArea.start;
+ hasAreaChanged =
+ hasAreaChanged || selectedArea.end !== this.previousArea.end;
hasAreaChanged = hasAreaChanged ||
selectedArea.tracks.length !== this.previousArea.tracks.length;
for (let i = 0; i < selectedArea.tracks.length; ++i) {
diff --git a/ui/src/controller/area_selection_handler_unittest.ts b/ui/src/controller/area_selection_handler_unittest.ts
index c5a27c0..caac678 100644
--- a/ui/src/controller/area_selection_handler_unittest.ts
+++ b/ui/src/controller/area_selection_handler_unittest.ts
@@ -20,7 +20,7 @@
test('validAreaAfterUndefinedArea', () => {
const areaId = '0';
- const latestArea: AreaById = {startSec: 0, endSec: 1, tracks: [], id: areaId};
+ const latestArea: AreaById = {start: 0n, end: 1n, tracks: [], id: areaId};
globals.state = createEmptyState();
globals.state.currentSelection = {kind: 'AREA', areaId};
globals.state.areas[areaId] = latestArea;
@@ -35,7 +35,7 @@
test('UndefinedAreaAfterValidArea', () => {
const previousAreaId = '0';
const previous:
- AreaById = {startSec: 0, endSec: 1, tracks: [], id: previousAreaId};
+ AreaById = {start: 0n, end: 1n, tracks: [], id: previousAreaId};
globals.state = createEmptyState();
globals.state.currentSelection = {
kind: 'AREA',
@@ -71,7 +71,7 @@
test('validAreaAfterValidArea', () => {
const previousAreaId = '0';
const previous:
- AreaById = {startSec: 0, endSec: 1, tracks: [], id: previousAreaId};
+ AreaById = {start: 0n, end: 1n, tracks: [], id: previousAreaId};
globals.state = createEmptyState();
globals.state.currentSelection = {
kind: 'AREA',
@@ -82,8 +82,7 @@
areaSelectionHandler.getAreaChange();
const currentAreaId = '1';
- const current:
- AreaById = {startSec: 1, endSec: 2, tracks: [], id: currentAreaId};
+ const current: AreaById = {start: 1n, end: 2n, tracks: [], id: currentAreaId};
globals.state.currentSelection = {
kind: 'AREA',
areaId: currentAreaId,
@@ -98,7 +97,7 @@
test('sameAreaSelected', () => {
const previousAreaId = '0';
const previous:
- AreaById = {startSec: 0, endSec: 1, tracks: [], id: previousAreaId};
+ AreaById = {start: 0n, end: 1n, tracks: [], id: previousAreaId};
globals.state = createEmptyState();
globals.state.currentSelection = {
kind: 'AREA',
@@ -109,8 +108,7 @@
areaSelectionHandler.getAreaChange();
const currentAreaId = '0';
- const current:
- AreaById = {startSec: 0, endSec: 1, tracks: [], id: currentAreaId};
+ const current: AreaById = {start: 0n, end: 1n, tracks: [], id: currentAreaId};
globals.state.currentSelection = {
kind: 'AREA',
areaId: currentAreaId,
@@ -128,7 +126,7 @@
areaSelectionHandler.getAreaChange();
globals.state
- .currentSelection = {kind: 'COUNTER', leftTs: 0, rightTs: 0, id: 1};
+ .currentSelection = {kind: 'COUNTER', leftTs: 0n, rightTs: 0n, id: 1};
const [hasAreaChanged, selectedArea] = areaSelectionHandler.getAreaChange();
expect(hasAreaChanged).toEqual(false);
diff --git a/ui/src/controller/flamegraph_controller.ts b/ui/src/controller/flamegraph_controller.ts
index e94531d..31a74c3 100644
--- a/ui/src/controller/flamegraph_controller.ts
+++ b/ui/src/controller/flamegraph_controller.ts
@@ -27,7 +27,7 @@
} from '../common/flamegraph_util';
import {NUM, STR} from '../common/query_result';
import {CallsiteInfo, FlamegraphState, ProfileType} from '../common/state';
-import {toNs} from '../common/time';
+import {tpDurationToSeconds, TPTime} from '../common/time';
import {FlamegraphDetails, globals} from '../frontend/globals';
import {publishFlamegraphDetails} from '../frontend/publish';
import {
@@ -145,8 +145,8 @@
}
globals.dispatch(Actions.openFlamegraph({
upids,
- startNs: toNs(area.startSec),
- endNs: toNs(area.endSec),
+ start: area.start,
+ end: area.end,
type: ProfileType.PERF_SAMPLE,
viewingOption: PERF_SAMPLES_KEY,
}));
@@ -169,8 +169,8 @@
const selectedFlamegraphState = {...selection};
const flamegraphMetadata = await this.getFlamegraphMetadata(
selection.type,
- selectedFlamegraphState.startNs,
- selectedFlamegraphState.endNs,
+ selectedFlamegraphState.start,
+ selectedFlamegraphState.end,
selectedFlamegraphState.upids);
if (flamegraphMetadata !== undefined) {
Object.assign(this.flamegraphDetails, flamegraphMetadata);
@@ -192,7 +192,7 @@
selectedFlamegraphState.expandedCallsite.totalSize;
const key = `${selectedFlamegraphState.upids};${
- selectedFlamegraphState.startNs};${selectedFlamegraphState.endNs}`;
+ selectedFlamegraphState.start};${selectedFlamegraphState.end}`;
try {
const flamegraphData = await this.getFlamegraphData(
@@ -200,15 +200,15 @@
selectedFlamegraphState.viewingOption ?
selectedFlamegraphState.viewingOption :
DEFAULT_VIEWING_OPTION,
- selection.startNs,
- selection.endNs,
+ selection.start,
+ selection.end,
selectedFlamegraphState.upids,
selectedFlamegraphState.type,
selectedFlamegraphState.focusRegex);
if (flamegraphData !== undefined && selection &&
selection.kind === selectedFlamegraphState.kind &&
- selection.startNs === selectedFlamegraphState.startNs &&
- selection.endNs === selectedFlamegraphState.endNs) {
+ selection.start === selectedFlamegraphState.start &&
+ selection.end === selectedFlamegraphState.end) {
const expandedFlamegraphData =
expandCallsites(flamegraphData, expandedId);
this.prepareAndMergeCallsites(
@@ -230,8 +230,8 @@
private shouldRequestData(selection: FlamegraphState) {
return selection.kind === 'FLAMEGRAPH_STATE' &&
(this.lastSelectedFlamegraphState === undefined ||
- (this.lastSelectedFlamegraphState.startNs !== selection.startNs ||
- this.lastSelectedFlamegraphState.endNs !== selection.endNs ||
+ (this.lastSelectedFlamegraphState.start !== selection.start ||
+ this.lastSelectedFlamegraphState.end !== selection.end ||
this.lastSelectedFlamegraphState.type !== selection.type ||
!FlamegraphController.areArraysEqual(
this.lastSelectedFlamegraphState.upids, selection.upids) ||
@@ -267,7 +267,7 @@
}
async getFlamegraphData(
- baseKey: string, viewingOption: string, startNs: number, endNs: number,
+ baseKey: string, viewingOption: string, start: TPTime, end: TPTime,
upids: number[], type: ProfileType,
focusRegex: string): Promise<CallsiteInfo[]> {
let currentData: CallsiteInfo[];
@@ -280,8 +280,8 @@
// 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(
- startNs, endNs, upids, type, focusRegex);
+ const tableName =
+ await this.prepareViewsAndTables(start, end, upids, type, focusRegex);
currentData = await this.getFlamegraphDataFromTables(
tableName, viewingOption, focusRegex);
this.flamegraphDatasets.set(key, currentData);
@@ -413,7 +413,7 @@
}
private async prepareViewsAndTables(
- startNs: number, endNs: number, upids: number[], type: ProfileType,
+ start: TPTime, end: TPTime, upids: number[], type: ProfileType,
focusRegex: string): Promise<string> {
// Creating unique names for views so we can reuse and not delete them
// for each marker.
@@ -437,8 +437,8 @@
cumulative_alloc_size, cumulative_count, cumulative_alloc_count,
size, alloc_size, count, alloc_count, source_file, line_number
from experimental_flamegraph
- where profile_type = '${flamegraphType}' and ${startNs} <= ts and
- ts <= ${endNs} and ${upidConditional}
+ where profile_type = '${flamegraphType}' and ${start} <= ts and
+ ts <= ${end} and ${upidConditional}
${focusRegexConditional}`);
}
return this.cache.getTableName(
@@ -447,7 +447,7 @@
size, alloc_size, count, alloc_count, source_file, line_number
from experimental_flamegraph
where profile_type = '${flamegraphType}'
- and ts = ${endNs}
+ and ts = ${end}
and upid = ${upids[0]}
${focusRegexConditional}`);
}
@@ -455,7 +455,8 @@
getMinSizeDisplayed(flamegraphData: CallsiteInfo[], rootSize?: number):
number {
const timeState = globals.state.frontendLocalState.visibleState;
- let width = (timeState.endSec - timeState.startSec) / timeState.resolution;
+ const dur = globals.stateVisibleTime().duration;
+ let width = tpDurationToSeconds(dur / timeState.resolution);
// TODO(168048193): Remove screen size hack:
width = Math.max(width, 800);
if (rootSize === undefined) {
@@ -465,11 +466,12 @@
}
async getFlamegraphMetadata(
- type: ProfileType, startNs: number, endNs: number, upids: number[]) {
+ type: ProfileType, start: TPTime, end: TPTime,
+ upids: number[]): Promise<FlamegraphDetails|undefined> {
// Don't do anything if selection of the marker stayed the same.
if ((this.lastSelectedFlamegraphState !== undefined &&
- ((this.lastSelectedFlamegraphState.startNs === startNs &&
- this.lastSelectedFlamegraphState.endNs === endNs &&
+ ((this.lastSelectedFlamegraphState.start === start &&
+ this.lastSelectedFlamegraphState.end === end &&
FlamegraphController.areArraysEqual(
this.lastSelectedFlamegraphState.upids, upids))))) {
return undefined;
@@ -486,7 +488,7 @@
for (let i = 0; it.valid(); ++i, it.next()) {
pids.push(it.pid);
}
- return {startNs, durNs: endNs - startNs, pids, upids, type};
+ return {start, dur: end - start, pids, upids, type};
}
private static areArraysEqual(a: number[], b: number[]) {
diff --git a/ui/src/controller/flow_events_controller.ts b/ui/src/controller/flow_events_controller.ts
index d89b514..07125e1 100644
--- a/ui/src/controller/flow_events_controller.ts
+++ b/ui/src/controller/flow_events_controller.ts
@@ -16,7 +16,7 @@
import {featureFlags} from '../common/feature_flags';
import {NUM, STR_NULL} from '../common/query_result';
import {Area} from '../common/state';
-import {fromNs, toNs} from '../common/time';
+import {fromNs} from '../common/time';
import {Flow, globals} from '../frontend/globals';
import {publishConnectedFlows, publishSelectedFlows} from '../frontend/publish';
import {
@@ -241,8 +241,8 @@
const area = globals.state.areas[areaId];
if (this.lastSelectedKind === 'AREA' && this.lastSelectedArea &&
this.lastSelectedArea.tracks.join(',') === area.tracks.join(',') &&
- this.lastSelectedArea.endSec === area.endSec &&
- this.lastSelectedArea.startSec === area.startSec) {
+ this.lastSelectedArea.end === area.end &&
+ this.lastSelectedArea.start === area.start) {
return;
}
@@ -268,8 +268,8 @@
const tracks = `(${trackIds.join(',')})`;
- const startNs = toNs(area.startSec);
- const endNs = toNs(area.endSec);
+ const startNs = area.start;
+ const endNs = area.end;
const query = `
select
diff --git a/ui/src/controller/ftrace_controller.ts b/ui/src/controller/ftrace_controller.ts
index f558a4a..a071ec5 100644
--- a/ui/src/controller/ftrace_controller.ts
+++ b/ui/src/controller/ftrace_controller.ts
@@ -13,9 +13,13 @@
// limitations under the License.
import {Engine} from '../common/engine';
-import {NUM, STR, STR_NULL} from '../common/query_result';
+import {
+ HighPrecisionTime,
+ HighPrecisionTimeSpan,
+} from '../common/high_precision_time';
+import {LONG, NUM, STR, STR_NULL} from '../common/query_result';
import {FtraceFilterState, Pagination} from '../common/state';
-import {TimeSpan, toNsCeil, toNsFloor} from '../common/time';
+import {Span} from '../common/time';
import {FtraceEvent, globals} from '../frontend/globals';
import {publishFtracePanelData} from '../frontend/publish';
import {ratelimit} from '../frontend/rate_limiters';
@@ -34,7 +38,7 @@
export class FtraceController extends Controller<'main'> {
private engine: Engine;
- private oldSpan: TimeSpan = new TimeSpan(0, 0);
+ private oldSpan: Span<HighPrecisionTime> = HighPrecisionTimeSpan.ZERO;
private oldFtraceFilter?: FtraceFilterState;
private oldPagination?: Pagination;
@@ -45,7 +49,7 @@
run() {
if (this.shouldUpdate()) {
- this.oldSpan = globals.frontendLocalState.visibleWindowTime.clone();
+ this.oldSpan = globals.frontendLocalState.visibleWindowTime;
this.oldFtraceFilter = globals.state.ftraceFilter;
this.oldPagination = globals.state.ftracePagination;
if (globals.state.ftracePagination.count > 0) {
@@ -66,8 +70,7 @@
private shouldUpdate(): boolean {
// Has the visible window moved?
const visibleWindow = globals.frontendLocalState.visibleWindowTime;
- if (this.oldSpan.start !== visibleWindow.start ||
- this.oldSpan.end !== visibleWindow.end) {
+ if (!this.oldSpan.equals(visibleWindow)) {
return true;
}
@@ -89,8 +92,8 @@
const frontendState = globals.frontendLocalState;
const {start, end} = frontendState.visibleWindowTime;
- const startNs = toNsFloor(start);
- const endNs = toNsCeil(end);
+ const startNs = start.nanos;
+ const endNs = end.nanos;
const excludeList = appState.ftraceFilter.excludedNames;
const excludeListSql = excludeList.map((s) => `'${s}'`).join(',');
@@ -132,7 +135,7 @@
const it = queryRes.iter(
{
id: NUM,
- ts: NUM,
+ ts: LONG,
name: STR,
cpu: NUM,
thread: STR_NULL,
diff --git a/ui/src/controller/logs_controller.ts b/ui/src/controller/logs_controller.ts
index d8f9b3a..c931ce0 100644
--- a/ui/src/controller/logs_controller.ts
+++ b/ui/src/controller/logs_controller.ts
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {BigintMath} from '../base/bigint_math';
import {Engine} from '../common/engine';
import {
LogBounds,
@@ -20,62 +21,61 @@
LogEntriesKey,
LogExistsKey,
} from '../common/logs';
-import {NUM, STR} from '../common/query_result';
+import {LONG, LONG_NULL, NUM, STR} from '../common/query_result';
import {escapeGlob, escapeQuery} from '../common/query_utils';
import {LogFilteringCriteria} from '../common/state';
-import {fromNs, TimeSpan, toNsCeil, toNsFloor} from '../common/time';
+import {Span} from '../common/time';
+import {
+ TPTime,
+ TPTimeSpan,
+} from '../common/time';
import {globals} from '../frontend/globals';
import {publishTrackData} from '../frontend/publish';
import {Controller} from './controller';
async function updateLogBounds(
- engine: Engine, span: TimeSpan): Promise<LogBounds> {
- const vizStartNs = toNsFloor(span.start);
- const vizEndNs = toNsCeil(span.end);
+ engine: Engine, span: Span<TPTime>): Promise<LogBounds> {
+ const vizStartNs = span.start;
+ const vizEndNs = span.end;
- const countResult = await engine.query(`select
- ifnull(min(ts), 0) as minTs,
- ifnull(max(ts), 0) as maxTs,
- count(ts) as countTs
- from filtered_logs
- where ts >= ${vizStartNs}
- and ts <= ${vizEndNs}`);
+ const vizFilter = `ts between ${vizStartNs} and ${vizEndNs}`;
- const countRow = countResult.firstRow({minTs: NUM, maxTs: NUM, countTs: NUM});
+ const result = await engine.query(`select
+ min(ts) as minTs,
+ max(ts) as maxTs,
+ min(case when ${vizFilter} then ts end) as minVizTs,
+ max(case when ${vizFilter} then ts end) as maxVizTs,
+ count(case when ${vizFilter} then ts end) as countTs
+ from filtered_logs`);
- const firstRowNs = countRow.minTs;
- const lastRowNs = countRow.maxTs;
- const total = countRow.countTs;
+ const data = result.firstRow({
+ minTs: LONG_NULL,
+ maxTs: LONG_NULL,
+ minVizTs: LONG_NULL,
+ maxVizTs: LONG_NULL,
+ countTs: NUM,
+ });
- const minResult = await engine.query(`
- select ifnull(max(ts), 0) as maxTs from filtered_logs where ts < ${
- vizStartNs}`);
- const startNs = minResult.firstRow({maxTs: NUM}).maxTs;
+ const firstLogTs = data.minTs ?? 0n;
+ const lastLogTs = data.maxTs ?? BigintMath.INT64_MAX;
- const maxResult = await engine.query(`
- select ifnull(min(ts), 0) as minTs from filtered_logs where ts > ${
- vizEndNs}`);
- const endNs = maxResult.firstRow({minTs: NUM}).minTs;
-
- const startTs = startNs ? fromNs(startNs) : 0;
- const endTs = endNs ? fromNs(endNs) : Number.MAX_SAFE_INTEGER;
- const firstRowTs = firstRowNs ? fromNs(firstRowNs) : endTs;
- const lastRowTs = lastRowNs ? fromNs(lastRowNs) : startTs;
- return {
- startTs,
- endTs,
- firstRowTs,
- lastRowTs,
- total,
+ const bounds: LogBounds = {
+ firstLogTs,
+ lastLogTs,
+ firstVisibleLogTs: data.minVizTs ?? firstLogTs,
+ lastVisibleLogTs: data.maxVizTs ?? lastLogTs,
+ totalVisibleLogs: data.countTs,
};
+
+ return bounds;
}
async function updateLogEntries(
- engine: Engine, span: TimeSpan, pagination: Pagination):
+ engine: Engine, span: Span<TPTime>, pagination: Pagination):
Promise<LogEntries> {
- const vizStartNs = toNsFloor(span.start);
- const vizEndNs = toNsCeil(span.end);
+ const vizStartNs = span.start;
+ const vizEndNs = span.end;
const vizSqlBounds = `ts >= ${vizStartNs} and ts <= ${vizEndNs}`;
const rowsResult = await engine.query(`
@@ -101,7 +101,7 @@
const processName = [];
const it = rowsResult.iter({
- ts: NUM,
+ ts: LONG,
prio: NUM,
tag: STR,
msg: STR,
@@ -179,7 +179,7 @@
*/
export class LogsController extends Controller<'main'> {
private engine: Engine;
- private span: TimeSpan;
+ private span: Span<TPTime>;
private pagination: Pagination;
private hasLogs = false;
private logFilteringCriteria?: LogFilteringCriteria;
@@ -189,7 +189,7 @@
constructor(args: LogsControllerArgs) {
super('main');
this.engine = args.engine;
- this.span = new TimeSpan(0, 10);
+ this.span = new TPTimeSpan(0n, BigInt(10e9));
this.pagination = new Pagination(0, 0);
this.hasAnyLogs().then((exists) => {
this.hasLogs = exists;
@@ -226,8 +226,7 @@
}
private async updateLogTracks() {
- const traceTime = globals.state.frontendLocalState.visibleState;
- const newSpan = new TimeSpan(traceTime.startSec, traceTime.endSec);
+ const newSpan = globals.stateVisibleTime();
const oldSpan = this.span;
const pagination = globals.state.logsPagination;
diff --git a/ui/src/controller/record_controller_jsdomtest.ts b/ui/src/controller/record_controller_jsdomtest.ts
index f160290..bc7c15b 100644
--- a/ui/src/controller/record_controller_jsdomtest.ts
+++ b/ui/src/controller/record_controller_jsdomtest.ts
@@ -32,7 +32,8 @@
const result =
TraceConfig.decode(genConfigProto(config, {os: 'Q', name: 'Android Q'}));
const sources = assertExists(result.dataSources);
- const srcConfig = assertExists(sources[0].config);
+ // TODO(hjd): This is all bad. Should just match the whole config.
+ const srcConfig = assertExists(sources[1].config);
const ftraceConfig = assertExists(srcConfig.ftraceConfig);
const ftraceEvents = assertExists(ftraceConfig.ftraceEvents);
expect(ftraceEvents.includes('raw_syscalls/sys_enter')).toBe(true);
@@ -45,7 +46,7 @@
const result =
TraceConfig.decode(genConfigProto(config, {os: 'S', name: 'Android S'}));
const sources = assertExists(result.dataSources);
- const srcConfig = assertExists(sources[1].config);
+ const srcConfig = assertExists(sources[2].config);
const ftraceConfig = assertExists(srcConfig.ftraceConfig);
const ftraceEvents = assertExists(ftraceConfig.ftraceEvents);
expect(ftraceConfig.symbolizeKsyms).toBe(true);
@@ -58,7 +59,7 @@
const result =
TraceConfig.decode(genConfigProto(config, {os: 'Q', name: 'Android Q'}));
const sources = assertExists(result.dataSources);
- const srcConfig = assertExists(sources[1].config);
+ const srcConfig = assertExists(sources[2].config);
const ftraceConfig = assertExists(srcConfig.ftraceConfig);
const ftraceEvents = assertExists(ftraceConfig.ftraceEvents);
expect(ftraceConfig.symbolizeKsyms).toBe(false);
@@ -72,7 +73,7 @@
const result =
TraceConfig.decode(genConfigProto(config, {os: 'Q', name: 'Android Q'}));
const sources = assertExists(result.dataSources);
- const srcConfig = assertExists(sources[0].config);
+ const srcConfig = assertExists(sources[1].config);
const ftraceConfig = assertExists(srcConfig.ftraceConfig);
const ftraceEvents = assertExists(ftraceConfig.ftraceEvents);
expect(ftraceConfig.symbolizeKsyms).toBe(true);
@@ -86,7 +87,7 @@
const result =
TraceConfig.decode(genConfigProto(config, {os: 'Q', name: 'Android Q'}));
const sources = assertExists(result.dataSources);
- const srcConfig = assertExists(sources[0].config);
+ const srcConfig = assertExists(sources[1].config);
const ftraceConfig = assertExists(srcConfig.ftraceConfig);
const ftraceEvents = assertExists(ftraceConfig.ftraceEvents);
expect(ftraceConfig.symbolizeKsyms).toBe(false);
diff --git a/ui/src/controller/search_controller.ts b/ui/src/controller/search_controller.ts
index d1df094..c5968c2 100644
--- a/ui/src/controller/search_controller.ts
+++ b/ui/src/controller/search_controller.ts
@@ -12,13 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {BigintMath} from '../base/bigint_math';
import {sqliteString} from '../base/string_utils';
import {Engine} from '../common/engine';
import {NUM, STR} from '../common/query_result';
import {escapeSearchQuery} from '../common/query_utils';
import {CurrentSearchResults, SearchSummary} from '../common/search_data';
-import {TimeSpan} from '../common/time';
-import {toNs} from '../common/time';
+import {Span} from '../common/time';
+import {
+ TPDuration,
+ TPTime,
+ TPTimeSpan,
+} from '../common/time';
import {globals} from '../frontend/globals';
import {publishSearch, publishSearchResult} from '../frontend/publish';
@@ -30,8 +35,8 @@
export class SearchController extends Controller<'main'> {
private engine: Engine;
- private previousSpan: TimeSpan;
- private previousResolution: number;
+ private previousSpan: Span<TPTime>;
+ private previousResolution: TPDuration;
private previousSearch: string;
private updateInProgress: boolean;
private setupInProgress: boolean;
@@ -39,11 +44,11 @@
constructor(args: SearchControllerArgs) {
super('main');
this.engine = args.engine;
- this.previousSpan = new TimeSpan(0, 1);
+ this.previousSpan = new TPTimeSpan(0n, 1n);
this.previousSearch = '';
this.updateInProgress = false;
this.setupInProgress = true;
- this.previousResolution = 1;
+ this.previousResolution = 1n;
this.setup().finally(() => {
this.setupInProgress = false;
this.run();
@@ -70,9 +75,9 @@
omniboxState.mode === 'COMMAND') {
return;
}
- const newSpan = new TimeSpan(visibleState.startSec, visibleState.endSec);
+ const newSpan = globals.stateVisibleTime();
const newSearch = omniboxState.omnibox;
- let newResolution = visibleState.resolution;
+ const newResolution = visibleState.resolution;
if (this.previousSpan.contains(newSpan) &&
this.previousResolution === newResolution &&
newSearch === this.previousSearch) {
@@ -83,9 +88,8 @@
// TODO(hjd): We should restrict this to the start of the trace but
// that is not easily available here.
// N.B. Timestamps can be negative.
- const start = newSpan.start - newSpan.duration;
- const end = newSpan.end + newSpan.duration;
- this.previousSpan = new TimeSpan(start, end);
+ const {start, end} = newSpan.pad(newSpan.duration);
+ this.previousSpan = new TPTimeSpan(start, end);
this.previousResolution = newResolution;
this.previousSearch = newSearch;
if (newSearch === '' || newSearch.length < 4) {
@@ -105,25 +109,12 @@
return;
}
- let startNs = toNs(newSpan.start);
- let endNs = toNs(newSpan.end);
-
- // TODO(hjd): We shouldn't need to be so defensive here:
- if (!Number.isFinite(startNs)) {
- startNs = 0;
- }
- if (!Number.isFinite(endNs)) {
- endNs = 1;
- }
- if (!Number.isFinite(newResolution)) {
- newResolution = 1;
- }
-
this.updateInProgress = true;
- const computeSummary = this.update(newSearch, startNs, endNs, newResolution)
- .then((summary) => {
- publishSearch(summary);
- });
+ const computeSummary =
+ this.update(newSearch, newSpan.start, newSpan.end, newResolution)
+ .then((summary) => {
+ publishSearch(summary);
+ });
const computeResults =
this.specificSearch(newSearch).then((searchResults) => {
@@ -140,15 +131,14 @@
onDestroy() {}
private async update(
- search: string, startNs: number, endNs: number,
- resolution: number): Promise<SearchSummary> {
- const quantumNs = Math.round(resolution * 10 * 1e9);
-
+ search: string, startNs: TPTime, endNs: TPTime,
+ resolution: TPDuration): Promise<SearchSummary> {
const searchLiteral = escapeSearchQuery(search);
- startNs = Math.floor(startNs / quantumNs) * quantumNs;
+ const quantumNs = resolution * 10n;
+ startNs = BigintMath.quantizeFloor(startNs, quantumNs);
- const windowDur = Math.max(endNs - startNs, 1);
+ const windowDur = BigintMath.max(endNs - startNs, 1n);
await this.query(`update search_summary_window set
window_start=${startNs},
window_dur=${windowDur},
diff --git a/ui/src/controller/selection_controller.ts b/ui/src/controller/selection_controller.ts
index 66cf3d0..b5a3907 100644
--- a/ui/src/controller/selection_controller.ts
+++ b/ui/src/controller/selection_controller.ts
@@ -16,14 +16,23 @@
import {Arg, Args} from '../common/arg_types';
import {Engine} from '../common/engine';
import {
+ LONG,
NUM,
NUM_NULL,
STR,
STR_NULL,
} from '../common/query_result';
import {ChromeSliceSelection} from '../common/state';
-import {fromNs, toNs} from '../common/time';
-import {SliceDetails, ThreadStateDetails} from '../frontend/globals';
+import {
+ tpDurationFromSql,
+ TPTime,
+ tpTimeFromSql,
+} from '../common/time';
+import {
+ CounterDetails,
+ SliceDetails,
+ ThreadStateDetails,
+} from '../frontend/globals';
import {globals} from '../frontend/globals';
import {
publishCounterDetails,
@@ -176,10 +185,10 @@
case 'id':
break;
case 'ts':
- ts = fromNs(Number(v)) - globals.state.traceTime.startSec;
+ ts = tpTimeFromSql(v);
break;
case 'thread_ts':
- threadTs = fromNs(Number(v));
+ threadTs = tpTimeFromSql(v);
break;
case 'absTime':
if (v) absTime = `${v}`;
@@ -188,10 +197,10 @@
name = `${v}`;
break;
case 'dur':
- dur = fromNs(Number(v));
+ dur = tpDurationFromSql(v);
break;
case 'thread_dur':
- threadDur = fromNs(Number(v));
+ threadDur = tpDurationFromSql(v);
break;
case 'category':
case 'cat':
@@ -326,13 +335,13 @@
const selection = globals.state.currentSelection;
if (result.numRows() > 0 && selection) {
const row = result.firstRow({
- ts: NUM,
- dur: NUM,
+ ts: LONG,
+ dur: LONG,
});
- const ts = row.ts;
- const timeFromStart = fromNs(ts) - globals.state.traceTime.startSec;
- const dur = fromNs(row.dur);
- const selected: ThreadStateDetails = {ts: timeFromStart, dur};
+ const selected: ThreadStateDetails = {
+ ts: row.ts,
+ dur: row.dur,
+ };
publishThreadStateDetails(selected);
}
}
@@ -353,8 +362,8 @@
const selection = globals.state.currentSelection;
if (result.numRows() > 0 && selection) {
const row = result.firstRow({
- ts: NUM,
- dur: NUM,
+ ts: LONG,
+ dur: LONG,
priority: NUM,
endState: STR_NULL,
utid: NUM,
@@ -362,15 +371,14 @@
threadStateId: NUM_NULL,
});
const ts = row.ts;
- const timeFromStart = fromNs(ts) - globals.state.traceTime.startSec;
- const dur = fromNs(row.dur);
+ const dur = row.dur;
const priority = row.priority;
const endState = row.endState;
const utid = row.utid;
const cpu = row.cpu;
const threadStateId = row.threadStateId || undefined;
const selected: SliceDetails = {
- ts: timeFromStart,
+ ts,
dur,
priority,
endState,
@@ -391,7 +399,8 @@
}
}
- async counterDetails(ts: number, rightTs: number, id: number) {
+ async counterDetails(ts: TPTime, rightTs: TPTime, id: number):
+ Promise<CounterDetails> {
const counter = await this.args.engine.query(
`SELECT value, track_id as trackId FROM counter WHERE id = ${id}`);
const row = counter.iter({
@@ -407,17 +416,15 @@
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 endTs = rightTs !== -1n ? rightTs : globals.state.traceTime.end;
const delta = value - previousValue;
const duration = endTs - ts;
- const startTime = fromNs(ts) - globals.state.traceTime.startSec;
const uiTrackId = globals.state.uiTrackIdByTraceTrackId[trackId];
const name = uiTrackId ? globals.state.tracks[uiTrackId].name : undefined;
- return {startTime, value, delta, duration, name};
+ return {startTime: ts, value, delta, duration, name};
}
- async schedulingDetails(ts: number, utid: number|Long) {
+ async schedulingDetails(ts: TPTime, utid: number|Long) {
// Find the ts of the first wakeup before the current slice.
const wakeResult = await this.args.engine.query(`
select ts, waker_utid as wakerUtid
@@ -430,7 +437,7 @@
return undefined;
}
- const wakeFirstRow = wakeResult.firstRow({ts: NUM, wakerUtid: NUM_NULL});
+ const wakeFirstRow = wakeResult.firstRow({ts: LONG, wakerUtid: NUM_NULL});
const wakeupTs = wakeFirstRow.ts;
const wakerUtid = wakeFirstRow.wakerUtid;
if (wakerUtid === null) {
@@ -449,7 +456,7 @@
// 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 (prevSchedResult.numRows() !== 0 &&
- wakeupTs < prevSchedResult.firstRow({ts: NUM}).ts) {
+ wakeupTs < prevSchedResult.firstRow({ts: LONG}).ts) {
return undefined;
}
@@ -468,7 +475,7 @@
}
const wakerRow = wakerResult.firstRow({cpu: NUM});
- return {wakeupTs: fromNs(wakeupTs), wakerUtid, wakerCpu: wakerRow.cpu};
+ return {wakeupTs, wakerUtid, wakerCpu: wakerRow.cpu};
}
async computeThreadDetails(utid: number):
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index b704e87..f0e2d02 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {BigintMath} from '../base/bigint_math';
import {assertExists, assertTrue} from '../base/logging';
import {
Actions,
@@ -20,15 +21,30 @@
import {cacheTrace} from '../common/cache_manager';
import {Engine} from '../common/engine';
import {featureFlags, Flag, PERF_SAMPLE_FLAG} from '../common/feature_flags';
+import {
+ HighPrecisionTime,
+ HighPrecisionTimeSpan,
+} from '../common/high_precision_time';
import {HttpRpcEngine} from '../common/http_rpc_engine';
import {
getEnabledMetatracingCategories,
isMetatracingEnabled,
} from '../common/metatracing';
-import {NUM, NUM_NULL, QueryError, STR, STR_NULL} from '../common/query_result';
+import {
+ LONG,
+ NUM,
+ NUM_NULL,
+ QueryError,
+ STR,
+ STR_NULL,
+} from '../common/query_result';
import {onSelectionChanged} from '../common/selection_observer';
import {defaultTraceTime, EngineMode, ProfileType} from '../common/state';
-import {TimeSpan, toNs, toNsCeil, toNsFloor} from '../common/time';
+import {Span} from '../common/time';
+import {
+ TPTime,
+ TPTimeSpan,
+} from '../common/time';
import {resetEngineWorker, WasmEngineProxy} from '../common/wasm_engine_proxy';
import {BottomTabList} from '../frontend/bottom_tab';
import {
@@ -39,6 +55,7 @@
} from '../frontend/globals';
import {showModal} from '../frontend/modal';
import {
+ clearOverviewData,
publishFtraceCounters,
publishMetricError,
publishOverviewData,
@@ -415,11 +432,11 @@
const traceUuid = await this.cacheCurrentTrace();
const traceTime = await this.engine.getTraceTimeBounds();
- const startSec = traceTime.start;
- const endSec = traceTime.end;
+ const start = traceTime.start;
+ const end = traceTime.end;
const traceTimeState = {
- startSec,
- endSec,
+ start,
+ end,
};
const shownJsonWarning =
@@ -452,16 +469,16 @@
Actions.setTraceTime(traceTimeState),
];
- const [startVisibleTime, endVisibleTime] =
- await computeVisibleTime(startSec, endSec, isJsonTrace, this.engine);
+ const visibleTimeSpan = await computeVisibleTime(
+ traceTime.start, traceTime.end, isJsonTrace, this.engine);
// We don't know the resolution at this point. However this will be
// replaced in 50ms so a guess is fine.
- const resolution = (endVisibleTime - startVisibleTime) / 1000;
+ const resolution = visibleTimeSpan.duration.divide(1000).toTPTime();
actions.push(Actions.setVisibleTraceTime({
- startSec: startVisibleTime,
- endSec: endVisibleTime,
+ start: visibleTimeSpan.start.toTPTime(),
+ end: visibleTimeSpan.end.toTPTime(),
lastUpdate: Date.now() / 1000,
- resolution,
+ resolution: BigintMath.max(resolution, 1n),
}));
globals.dispatchMultiple(actions);
@@ -539,8 +556,8 @@
if (profile.numRows() !== 1) return;
const row = profile.firstRow({upid: NUM});
const upid = row.upid;
- const leftTs = toNs(globals.state.traceTime.startSec);
- const rightTs = toNs(globals.state.traceTime.endSec);
+ const leftTs = globals.state.traceTime.start;
+ const rightTs = globals.state.traceTime.end;
globals.dispatch(Actions.selectPerfSamples(
{id: 0, upid, leftTs, rightTs, type: ProfileType.PERF_SAMPLE}));
}
@@ -559,7 +576,7 @@
order by ts limit 1`;
const profile = await assertExists(this.engine).query(query);
if (profile.numRows() !== 1) return;
- const row = profile.firstRow({ts: NUM, type: STR, upid: NUM});
+ const row = profile.firstRow({ts: LONG, type: STR, upid: NUM});
const ts = row.ts;
const type = profileType(row.type);
const upid = row.upid;
@@ -609,31 +626,32 @@
publishThreads(threads);
}
- private async loadTimelineOverview(traceTime: TimeSpan) {
+ private async loadTimelineOverview(trace: Span<TPTime>) {
+ clearOverviewData();
+
const engine = assertExists<Engine>(this.engine);
- const numSteps = 100;
- const stepSec = traceTime.duration / numSteps;
+ const stepSize = BigintMath.max(1n, trace.duration / 100n);
let hasSchedOverview = false;
- for (let step = 0; step < numSteps; step++) {
+ for (let start = trace.start; start < trace.end; start += stepSize) {
+ const progress = start - trace.start;
+ const ratio = Number(progress) / Number(trace.duration);
this.updateStatus(
- 'Loading overview ' +
- `${Math.round((step + 1) / numSteps * 1000) / 10}%`);
- const startSec = traceTime.start + step * stepSec;
- const startNs = toNsFloor(startSec);
- const endSec = startSec + stepSec;
- const endNs = toNsCeil(endSec);
+ 'Loading overview ' +
+ `${Math.round(ratio * 100)}%`);
+ const end = start + stepSize;
// Sched overview.
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');
+ `select cast(sum(dur) as float)/${
+ stepSize} as load, cpu from sched ` +
+ `where ts >= ${start} and ts < ${end} and utid != 0 ` +
+ 'group by cpu order by cpu');
const schedData: {[key: string]: QuantizedLoad} = {};
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};
+ schedData[cpu] = {start, end, load};
hasSchedOverview = true;
}
publishOverviewData(schedData);
@@ -644,16 +662,15 @@
}
// Slices overview.
- const traceStartNs = toNs(traceTime.start);
- const stepSecNs = toNs(stepSec);
const sliceResult = await engine.query(`select
bucket,
upid,
- ifnull(sum(utid_sum) / cast(${stepSecNs} as float), 0) as load
+ ifnull(sum(utid_sum) / cast(${stepSize} as float), 0) as load
from thread
inner join (
select
- ifnull(cast((ts - ${traceStartNs})/${stepSecNs} as int), 0) as bucket,
+ ifnull(cast((ts - ${trace.start})/${
+ stepSize} as int), 0) as bucket,
sum(dur) as utid_sum,
utid
from slice
@@ -664,21 +681,21 @@
group by bucket, upid`);
const slicesData: {[key: string]: QuantizedLoad[]} = {};
- const it = sliceResult.iter({bucket: NUM, upid: NUM, load: NUM});
+ const it = sliceResult.iter({bucket: LONG, 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;
+ const start = trace.start + stepSize * bucket;
+ const end = start + stepSize;
const upidStr = upid.toString();
let loadArray = slicesData[upidStr];
if (loadArray === undefined) {
loadArray = slicesData[upidStr] = [];
}
- loadArray.push({startSec, endSec, load});
+ loadArray.push({start, end, load});
}
publishOverviewData(slicesData);
}
@@ -889,48 +906,48 @@
}
}
-async function computeTraceReliableRangeStart(engine: Engine): Promise<number> {
+async function computeTraceReliableRangeStart(engine: Engine): Promise<TPTime> {
const result =
await engine.query(`SELECT RUN_METRIC('chrome/chrome_reliable_range.sql');
SELECT start FROM chrome_reliable_range`);
- const bounds = result.firstRow({start: NUM});
- return bounds.start / 1e9;
+ const bounds = result.firstRow({start: LONG});
+ return bounds.start;
}
async function computeVisibleTime(
- traceStartSec: number,
- traceEndSec: number,
- isJsonTrace: boolean,
- engine: Engine): Promise<[number, number]> {
+ traceStart: TPTime, traceEnd: TPTime, isJsonTrace: boolean, engine: Engine):
+ Promise<Span<HighPrecisionTime>> {
// if we have non-default visible state, update the visible time to it
- const previousVisibleState = globals.state.frontendLocalState.visibleState;
- if (!(previousVisibleState.startSec === defaultTraceTime.startSec &&
- previousVisibleState.endSec === defaultTraceTime.endSec) &&
- (previousVisibleState.startSec >= traceStartSec &&
- previousVisibleState.endSec <= traceEndSec)) {
- return [previousVisibleState.startSec, previousVisibleState.endSec];
+ const previousVisibleState = globals.stateVisibleTime();
+ const defaultTraceSpan =
+ new TPTimeSpan(defaultTraceTime.start, defaultTraceTime.end);
+ if (!(previousVisibleState.start === defaultTraceSpan.start &&
+ previousVisibleState.end === defaultTraceSpan.end) &&
+ (previousVisibleState.start >= traceStart &&
+ previousVisibleState.end <= traceEnd)) {
+ return HighPrecisionTimeSpan.fromTpTime(
+ previousVisibleState.start, previousVisibleState.end);
}
// initialise visible time to the trace time bounds
- let visibleStartSec = traceStartSec;
- let visibleEndSec = traceEndSec;
+ let visibleStartSec = traceStart;
+ let visibleEndSec = traceEnd;
// compare start and end with metadata computed by the trace processor
const mdTime = await engine.getTracingMetadataTimeBounds();
// make sure the bounds hold
- if (Math.max(visibleStartSec, mdTime.start) <
- Math.min(visibleEndSec, mdTime.end)) {
- visibleStartSec =
- Math.max(visibleStartSec, mdTime.start);
- visibleEndSec = Math.min(visibleEndSec, mdTime.end);
+ if (BigintMath.max(visibleStartSec, mdTime.start) <
+ BigintMath.min(visibleEndSec, mdTime.end)) {
+ visibleStartSec = BigintMath.max(visibleStartSec, mdTime.start);
+ visibleEndSec = BigintMath.min(visibleEndSec, mdTime.end);
}
// Trace Processor doesn't support the reliable range feature for JSON
// traces.
if (!isJsonTrace && ENABLE_CHROME_RELIABLE_RANGE_ZOOM_FLAG.get()) {
const reliableRangeStart = await computeTraceReliableRangeStart(engine);
- visibleStartSec = Math.max(visibleStartSec, reliableRangeStart);
+ visibleStartSec = BigintMath.max(visibleStartSec, reliableRangeStart);
}
- return [visibleStartSec, visibleEndSec];
+ return HighPrecisionTimeSpan.fromTpTime(visibleStartSec, visibleEndSec);
}
diff --git a/ui/src/controller/track_controller.ts b/ui/src/controller/track_controller.ts
index 46d1f1f..73b9896 100644
--- a/ui/src/controller/track_controller.ts
+++ b/ui/src/controller/track_controller.ts
@@ -12,11 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {BigintMath} from '../base/bigint_math';
import {assertExists, assertTrue} from '../base/logging';
import {Engine} from '../common/engine';
import {Registry} from '../common/registry';
import {TraceTime, TrackState} from '../common/state';
-import {fromNs, toNs} from '../common/time';
+import {
+ TPDuration,
+ TPTime,
+ tpTimeFromSeconds,
+ TPTimeSpan,
+} from '../common/time';
import {LIMIT, TrackData} from '../common/track_data';
import {globals} from '../frontend/globals';
import {publishTrackData} from '../frontend/publish';
@@ -70,7 +76,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 onBoundsChange(start: number, end: number, resolution: number):
+ abstract onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data>;
get trackState(): TrackState {
@@ -129,6 +135,7 @@
}
shouldRequestData(traceTime: TraceTime): boolean {
+ const tspan = new TPTimeSpan(traceTime.start, traceTime.end);
if (this.data === undefined) return true;
if (this.shouldReload()) return true;
@@ -137,15 +144,14 @@
if (atLimit) {
// We request more data than the window, so add window duration to find
// the previous window.
- const prevWindowStart =
- this.data.start + (traceTime.startSec - traceTime.endSec);
- return traceTime.startSec !== prevWindowStart;
+ const prevWindowStart = this.data.start + tspan.duration;
+ return tspan.start !== prevWindowStart;
}
// Otherwise request more data only when out of range of current data or
// resolution has changed.
- const inRange = traceTime.startSec >= this.data.start &&
- traceTime.endSec <= this.data.end;
+ const inRange =
+ tspan.start >= this.data.start && tspan.end <= this.data.end;
return !inRange ||
this.data.resolution !==
globals.state.frontendLocalState.visibleState.resolution;
@@ -162,8 +168,7 @@
return undefined;
}
- const bounds = globals.state.traceTime;
- const traceDurNs = toNs(bounds.endSec - bounds.startSec);
+ const traceDuration = globals.stateTraceTime().duration;
// For large traces, going through the raw table in the most zoomed-out
// states can be very expensive as this can involve going through O(millions
@@ -198,7 +203,7 @@
// Compute the outermost bucket size. This acts as a starting point for
// computing the cached size.
const outermostResolutionLevel =
- Math.ceil(Math.log2(traceDurNs / approxWidthPx));
+ Math.ceil(Math.log2(traceDuration.nanos / approxWidthPx));
const outermostBucketNs = Math.pow(2, outermostResolutionLevel);
// This constant decides how many resolution levels down from our outermost
@@ -232,11 +237,11 @@
run() {
const visibleState = globals.state.frontendLocalState.visibleState;
- if (visibleState === undefined || visibleState.resolution === undefined ||
- visibleState.resolution === Infinity) {
+ if (visibleState === undefined) {
return;
}
- const dur = visibleState.endSec - visibleState.startSec;
+ const visibleTimeSpan = globals.stateVisibleTime();
+ const dur = visibleTimeSpan.duration;
if (globals.state.visibleTracks.includes(this.trackId) &&
this.shouldRequestData(visibleState)) {
if (this.requestingData) {
@@ -253,16 +258,14 @@
.then(() => {
this.isSetup = true;
let resolution = visibleState.resolution;
- // TODO(hjd): We shouldn't have to be so defensive here.
- if (Math.log2(toNs(resolution)) % 1 !== 0) {
- // resolution is in pixels per second so 1000 means
- // 1px = 1ms.
- resolution =
- fromNs(Math.pow(2, Math.floor(Math.log2(toNs(1000)))));
+
+ if (BigintMath.popcount(resolution) !== 1) {
+ resolution = BigintMath.bitFloor(tpTimeFromSeconds(1000));
}
+
return this.onBoundsChange(
- visibleState.startSec - dur,
- visibleState.endSec + dur,
+ visibleTimeSpan.start - dur,
+ visibleTimeSpan.end + dur,
resolution);
})
.then((data) => {
diff --git a/ui/src/controller/track_decider.ts b/ui/src/controller/track_decider.ts
index 0653552..aadb889 100644
--- a/ui/src/controller/track_decider.ts
+++ b/ui/src/controller/track_decider.ts
@@ -25,6 +25,7 @@
import {featureFlags, PERF_SAMPLE_FLAG} from '../common/feature_flags';
import {pluginManager} from '../common/plugins';
import {
+ LONG_NULL,
NUM,
NUM_NULL,
STR,
@@ -61,6 +62,12 @@
PROCESS_SCHEDULING_TRACK_KIND,
} from '../tracks/process_scheduling';
import {PROCESS_SUMMARY_TRACK} from '../tracks/process_summary';
+import {
+ ENABLE_SCROLL_JANK_PLUGIN_V2,
+ INPUT_LATENCY_TRACK,
+} from '../tracks/scroll_jank';
+import {addLatenciesTrack} from '../tracks/scroll_jank/event_latency_track';
+import {addTopLevelScrollTrack} from '../tracks/scroll_jank/scroll_track';
import {THREAD_STATE_TRACK_KIND} from '../tracks/thread_state';
const TRACKS_V2_FLAG = featureFlags.register({
@@ -191,14 +198,39 @@
return 'Unknown';
}
+ async guessCpuSizes(): Promise<Map<number, string>> {
+ const cpuToSize = new Map<number, string>();
+ await this.engine.query(`
+ SELECT IMPORT('common.cpus');
+ `);
+ const result = await this.engine.query(`
+ SELECT cpu, GUESS_CPU_SIZE(cpu) as size FROM cpu_counter_track;
+ `);
+
+ const it = result.iter({
+ cpu: NUM,
+ size: STR,
+ });
+
+ for (; it.valid(); it.next()) {
+ cpuToSize.set(it.cpu, it.size);
+ }
+
+ return cpuToSize;
+ }
+
async addCpuSchedulingTracks(): Promise<void> {
const cpus = await this.engine.getCpus();
+ const cpuToSize = await this.guessCpuSizes();
+
for (const cpu of cpus) {
+ const size = cpuToSize.get(cpu);
+ const name = size === undefined ? `Cpu ${cpu}` : `Cpu ${cpu} (${size})`;
this.tracksToAdd.push({
engineId: this.engineId,
kind: CPU_SLICE_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
- name: `Cpu ${cpu}`,
+ name,
trackGroup: SCROLLING_TRACK_GROUP,
config: {
cpu,
@@ -207,6 +239,25 @@
}
}
+ async addScrollJankTracks(engine: Engine): Promise<void> {
+ const topLevelScrolls = addTopLevelScrollTrack(engine);
+ const topLevelScrollsResult = await topLevelScrolls;
+ let originalLength = this.tracksToAdd.length;
+ this.tracksToAdd.length += topLevelScrollsResult.tracksToAdd.length;
+ for (let i = 0; i < topLevelScrollsResult.tracksToAdd.length; ++i) {
+ this.tracksToAdd[i + originalLength] =
+ topLevelScrollsResult.tracksToAdd[i];
+ }
+
+ originalLength = this.tracksToAdd.length;
+ const eventLatencies = addLatenciesTrack(engine);
+ const eventLatencyResult = await eventLatencies;
+ this.tracksToAdd.length += eventLatencyResult.tracksToAdd.length;
+ for (let i = 0; i < eventLatencyResult.tracksToAdd.length; ++i) {
+ this.tracksToAdd[i + originalLength] = eventLatencyResult.tracksToAdd[i];
+ }
+ }
+
async addCpuFreqTracks(engine: EngineProxy): Promise<void> {
const cpus = await this.engine.getCpus();
@@ -309,6 +360,7 @@
});
const parentIdToGroupId = new Map<number, string>();
+ let scrollJankRendered = false;
for (; it.valid(); it.next()) {
const kind = ASYNC_SLICE_TRACK_KIND;
@@ -353,6 +405,13 @@
}
}
+ if (ENABLE_SCROLL_JANK_PLUGIN_V2.get() && !scrollJankRendered &&
+ name.includes(INPUT_LATENCY_TRACK)) {
+ // This ensures that the scroll jank tracks render above the tracks
+ // for GestureScrollUpdate.
+ await this.addScrollJankTracks(this.engine);
+ scrollJankRendered = true;
+ }
const track = {
engineId: this.engineId,
kind,
@@ -959,9 +1018,9 @@
upid: NUM_NULL,
tid: NUM_NULL,
threadName: STR_NULL,
- startTs: NUM_NULL,
+ startTs: LONG_NULL,
trackId: NUM,
- endTs: NUM_NULL,
+ endTs: LONG_NULL,
});
for (; it.valid(); it.next()) {
const utid = it.utid;
@@ -1276,8 +1335,8 @@
upid: NUM,
pid: NUM_NULL,
processName: STR_NULL,
- startTs: NUM_NULL,
- endTs: NUM_NULL,
+ startTs: LONG_NULL,
+ endTs: LONG_NULL,
});
for (let i = 0; it.valid(); ++i, it.next()) {
const pid = it.pid;
diff --git a/ui/src/frontend/aggregation_panel.ts b/ui/src/frontend/aggregation_panel.ts
index ddcb6ba..6bd6422 100644
--- a/ui/src/frontend/aggregation_panel.ts
+++ b/ui/src/frontend/aggregation_panel.ts
@@ -22,6 +22,7 @@
} from '../common/aggregation_data';
import {colorForState, textColorForState} from '../common/colorizer';
import {translateState} from '../common/thread_state';
+import {tpTimeToMillis} from '../common/time';
import {globals} from './globals';
import {Panel} from './panel';
@@ -111,7 +112,8 @@
const selection = globals.state.currentSelection;
if (selection === null || selection.kind !== 'AREA') return undefined;
const selectedArea = globals.state.areas[selection.areaId];
- const rangeDurationMs = (selectedArea.endSec - selectedArea.startSec) * 1e3;
+ const rangeDurationMs =
+ tpTimeToMillis(selectedArea.end - selectedArea.start);
return m('.time-range', `Selected range: ${rangeDurationMs.toFixed(6)} ms`);
}
diff --git a/ui/src/frontend/base_slice_track.ts b/ui/src/frontend/base_slice_track.ts
index ac3cad0..77c6e6d 100644
--- a/ui/src/frontend/base_slice_track.ts
+++ b/ui/src/frontend/base_slice_track.ts
@@ -22,7 +22,12 @@
} from '../common/colorizer';
import {NUM} from '../common/query_result';
import {Selection, SelectionKind} from '../common/state';
-import {fromNs, toNs} from '../common/time';
+import {
+ fromNs,
+ tpDurationFromNanos,
+ TPTime,
+ tpTimeFromNanos,
+} from '../common/time';
import {checkerboardExcept} from './checkerboard';
import {globals} from './globals';
@@ -45,7 +50,7 @@
// Exposed and standalone to allow for testing without making this
// visible to subclasses.
function filterVisibleSlices<S extends Slice>(
- slices: S[], startS: number, endS: number): S[] {
+ slices: S[], start: TPTime, end: TPTime): S[] {
// Here we aim to reduce the number of slices we have to draw
// by ignoring those that are not visible. A slice is visible iff:
// slice.start + slice.duration >= start && slice.start <= end
@@ -89,7 +94,7 @@
// For all slice in slices: slice.startS > endS (e.g. all slices are to the
// right). Since the slices are sorted by startS we can check this easily:
const maybeFirstSlice: S|undefined = slices[0];
- if (maybeFirstSlice && maybeFirstSlice.startS > endS) {
+ if (maybeFirstSlice && maybeFirstSlice.start > end) {
return [];
}
// It's not possible to easily check the analogous edge case where all slices
@@ -108,15 +113,15 @@
let endIdx = slices.length;
for (; startIdx < endIdx; ++startIdx) {
const slice = slices[startIdx];
- const sliceEndS = slice.startS + slice.durationS;
- if (sliceEndS >= startS && slice.startS <= endS) {
+ const sliceEndS = slice.start + slice.duration;
+ if (sliceEndS >= start && slice.start <= end) {
break;
}
}
for (; startIdx < endIdx; --endIdx) {
const slice = slices[endIdx - 1];
- const sliceEndS = slice.startS + slice.durationS;
- if (sliceEndS >= startS && slice.startS <= endS) {
+ const sliceEndS = slice.start + slice.duration;
+ if (sliceEndS >= start && slice.start <= end) {
break;
}
}
@@ -181,7 +186,7 @@
private cache: TrackCache<Array<CastInternal<T['slice']>>> =
new TrackCache(5);
- private readonly tableName: string;
+ protected readonly tableName: string;
private maxDurNs = 0;
private sqlState: 'UNINITIALIZED'|'INITIALIZING'|'QUERY_PENDING'|
'QUERY_DONE' = 'UNINITIALIZED';
@@ -272,13 +277,16 @@
renderCanvas(ctx: CanvasRenderingContext2D): void {
// TODO(hjd): fonts and colors should come from the CSS and not hardcoded
// here.
- const timeScale = globals.frontendLocalState.timeScale;
- const vizTime = globals.frontendLocalState.visibleWindowTime;
+ const {
+ visibleTimeScale: timeScale,
+ visibleWindowTime: vizTime,
+ } = globals.frontendLocalState;
{
- const windowSizePx = Math.max(1, timeScale.endPx - timeScale.startPx);
- const rawStartNs = toNs(vizTime.start);
- const rawEndNs = toNs(vizTime.end);
+ const windowSizePx = Math.max(1, timeScale.pxSpan.delta);
+ // TODO(stevegolton): Keep these guys as bigints
+ const rawStartNs = vizTime.start.nanos;
+ const rawEndNs = vizTime.end.nanos;
const rawSlicesKey = CacheKey.create(rawStartNs, rawEndNs, windowSizePx);
// If the visible time range is outside the cached area, requests
@@ -298,7 +306,8 @@
// Filter only the visible slices. |this.slices| will have more slices than
// needed because maybeRequestData() over-fetches to handle small pan/zooms.
// We don't want to waste time drawing slices that are off screen.
- const vizSlices = this.getVisibleSlicesInternal(vizTime.start, vizTime.end);
+ const vizSlices = this.getVisibleSlicesInternal(
+ vizTime.start.toTPTime('floor'), vizTime.end.toTPTime('ceil'));
let selection = globals.state.currentSelection;
@@ -321,15 +330,15 @@
// pxEnd is the last visible pixel in the visible viewport. Drawing
// anything < 0 or > pxEnd doesn't produce any visible effect as it goes
// beyond the visible portion of the canvas.
- const pxEnd = Math.floor(timeScale.timeToPx(vizTime.end));
+ const pxEnd = Math.floor(timeScale.hpTimeToPx(vizTime.end));
for (const slice of vizSlices) {
// Compute the basic geometry for any visible slice, even if only
// partially visible. This might end up with a negative x if the
// slice starts before the visible time or with a width that overflows
// pxEnd.
- slice.x = timeScale.timeToPx(slice.startS);
- slice.w = timeScale.deltaTimeToPx(slice.durationS);
+ slice.x = timeScale.tpTimeToPx(slice.start);
+ slice.w = timeScale.durationToPx(slice.duration);
if (slice.flags & SLICE_FLAGS_INSTANT) {
// In the case of an instant slice, set the slice geometry on the
// bounding box that will contain the chevron.
@@ -429,10 +438,10 @@
checkerboardExcept(
ctx,
this.getHeight(),
- timeScale.timeToPx(vizTime.start),
- timeScale.timeToPx(vizTime.end),
- timeScale.timeToPx(fromNs(this.slicesKey.startNs)),
- timeScale.timeToPx(fromNs(this.slicesKey.endNs)));
+ timeScale.hpTimeToPx(vizTime.start),
+ timeScale.hpTimeToPx(vizTime.end),
+ timeScale.secondsToPx(fromNs(this.slicesKey.startNs)),
+ timeScale.secondsToPx(fromNs(this.slicesKey.endNs)));
// TODO(hjd): Remove this.
// The only thing this does is drawing the sched latency arrow. We should
@@ -623,8 +632,8 @@
return {
id: row.id,
- startS: fromNs(startNsQ),
- durationS: fromNs(endNsQ - startNsQ),
+ start: tpTimeFromNanos(startNsQ),
+ duration: tpDurationFromNanos(endNsQ - startNsQ),
flags,
depth: row.depth,
title: '',
@@ -701,10 +710,10 @@
return true;
}
- private getVisibleSlicesInternal(startS: number, endS: number):
+ private getVisibleSlicesInternal(start: TPTime, end: TPTime):
Array<CastInternal<T['slice']>> {
return filterVisibleSlices<CastInternal<T['slice']>>(
- this.slices, startS, endS);
+ this.slices, start, end);
}
private updateSliceAndTrackHeight() {
diff --git a/ui/src/frontend/base_slice_track_unittest.ts b/ui/src/frontend/base_slice_track_unittest.ts
index 7dd109d..e9202a2 100644
--- a/ui/src/frontend/base_slice_track_unittest.ts
+++ b/ui/src/frontend/base_slice_track_unittest.ts
@@ -19,11 +19,11 @@
} from './base_slice_track';
import {Slice} from './slice';
-function slice(startS: number, durationS: number): Slice {
+function slice(start: number, duration: number): Slice {
return {
id: 42,
- startS,
- durationS,
+ start: BigInt(start),
+ duration: BigInt(duration),
depth: 0,
flags: 0,
title: '',
@@ -36,24 +36,24 @@
const s = slice;
test('filterVisibleSlices', () => {
- expect(filterVisibleSlices([], 0, 100)).toEqual([]);
- expect(filterVisibleSlices([s(10, 80)], 0, 100)).toEqual([s(10, 80)]);
- expect(filterVisibleSlices([s(0, 20)], 10, 100)).toEqual([s(0, 20)]);
- expect(filterVisibleSlices([s(0, 10)], 10, 100)).toEqual([s(0, 10)]);
- expect(filterVisibleSlices([s(100, 10)], 10, 100)).toEqual([s(100, 10)]);
- expect(filterVisibleSlices([s(10, 0)], 10, 100)).toEqual([s(10, 0)]);
- expect(filterVisibleSlices([s(100, 0)], 10, 100)).toEqual([s(100, 0)]);
- expect(filterVisibleSlices([s(0, 5)], 10, 90)).toEqual([]);
- expect(filterVisibleSlices([s(95, 5)], 10, 90)).toEqual([]);
- expect(filterVisibleSlices([s(0, 5), s(95, 5)], 10, 90)).toEqual([]);
+ expect(filterVisibleSlices([], 0n, 100n)).toEqual([]);
+ expect(filterVisibleSlices([s(10, 80)], 0n, 100n)).toEqual([s(10, 80)]);
+ expect(filterVisibleSlices([s(0, 20)], 10n, 100n)).toEqual([s(0, 20)]);
+ expect(filterVisibleSlices([s(0, 10)], 10n, 100n)).toEqual([s(0, 10)]);
+ expect(filterVisibleSlices([s(100, 10)], 10n, 100n)).toEqual([s(100, 10)]);
+ expect(filterVisibleSlices([s(10, 0)], 10n, 100n)).toEqual([s(10, 0)]);
+ expect(filterVisibleSlices([s(100, 0)], 10n, 100n)).toEqual([s(100, 0)]);
+ expect(filterVisibleSlices([s(0, 5)], 10n, 90n)).toEqual([]);
+ expect(filterVisibleSlices([s(95, 5)], 10n, 90n)).toEqual([]);
+ expect(filterVisibleSlices([s(0, 5), s(95, 5)], 10n, 90n)).toEqual([]);
expect(filterVisibleSlices(
[
s(0, 5),
s(50, 0),
s(95, 5),
],
- 10,
- 90))
+ 10n,
+ 90n))
.toEqual([
s(50, 0),
]);
@@ -63,8 +63,8 @@
s(1, 9),
s(6, 3),
],
- 10,
- 90))
+ 10n,
+ 90n))
.toContainEqual(s(1, 9));
expect(filterVisibleSlices(
[
@@ -73,16 +73,16 @@
s(6, 3),
s(50, 0),
],
- 10,
- 90))
+ 10n,
+ 90n))
.toContainEqual(s(1, 9));
expect(filterVisibleSlices(
[
s(85, 10),
s(100, 10),
],
- 10,
- 90))
+ 10n,
+ 90n))
.toEqual([
s(85, 10),
]);
@@ -91,8 +91,8 @@
s(0, 100),
],
- 10,
- 90))
+ 10n,
+ 90n))
.toEqual([
s(0, 100),
]);
@@ -109,7 +109,7 @@
s(8, 1),
s(9, 1),
],
- 10,
- 90))
+ 10n,
+ 90n))
.toContainEqual(s(5, 10));
});
diff --git a/ui/src/frontend/chrome_slice_panel.ts b/ui/src/frontend/chrome_slice_panel.ts
index 6c982cf..50e3d1c 100644
--- a/ui/src/frontend/chrome_slice_panel.ts
+++ b/ui/src/frontend/chrome_slice_panel.ts
@@ -17,7 +17,9 @@
import {sqliteString} from '../base/string_utils';
import {Actions} from '../common/actions';
import {Arg, ArgsTree, isArgTreeArray, isArgTreeMap} from '../common/arg_types';
-import {timeToCode} from '../common/time';
+import {EngineProxy} from '../common/engine';
+import {runQuery} from '../common/queries';
+import {timeToCode, tpDurationToSeconds, tpTimeToCode} from '../common/time';
import {FlowPoint, globals, SliceDetails} from './globals';
import {PanelSize} from './panel';
@@ -54,6 +56,29 @@
),
},
{
+ name: 'Binder call names',
+ shouldDisplay: () => true,
+ getAction: (slice: SliceDetails) => {
+ const engine = getEngine();
+ if (engine === undefined) return;
+ runQuery(`SELECT IMPORT('android.binder');`, engine)
+ .then(
+ () => runQueryInNewTab(
+ `
+ SELECT s.ts, s.dur, tx.aidl_name AS name, s.id
+ FROM android_sync_binder_metrics_by_txn tx
+ JOIN slice s ON tx.binder_txn_id = s.id
+ JOIN thread_track ON s.track_id = thread_track.id
+ JOIN thread USING (utid)
+ JOIN process USING (upid)
+ WHERE aidl_name IS NOT NULL
+ AND pid = ${slice.pid}
+ AND tid = ${slice.tid}`,
+ `Binder names (${slice.processName}:${slice.tid})`,
+ ));
+ },
+ },
+ {
name: 'Lock graph',
shouldDisplay: (slice: SliceDetails) => slice.id !== undefined,
getAction: (slice: SliceDetails) => runQueryInNewTab(
@@ -110,6 +135,15 @@
});
}
+function getEngine(): EngineProxy|undefined {
+ const engineId = globals.getCurrentEngine()?.id;
+ if (engineId === undefined) {
+ return undefined;
+ }
+ const engine = globals.engines.get(engineId)?.getProxy('SlicePanel');
+ return engine;
+}
+
// Table row contents is one of two things:
// 1. Key-value pair
interface TableRow {
@@ -261,7 +295,9 @@
!sliceInfo.category || sliceInfo.category === '[NULL]' ?
'N/A' :
sliceInfo.category);
- defaultBuilder.add('Start time', timeToCode(sliceInfo.ts));
+ defaultBuilder.add(
+ 'Start time',
+ tpTimeToCode(sliceInfo.ts - globals.state.traceTime.start));
if (sliceInfo.absTime !== undefined) {
defaultBuilder.add('Absolute Time', sliceInfo.absTime);
}
@@ -271,9 +307,11 @@
sliceInfo.threadDur !== undefined) {
// If we have valid thread duration, also display a percentage of
// |threadDur| compared to |dur|.
- const threadDurFractionSuffix = sliceInfo.threadDur === -1 ?
+ const ratio = tpDurationToSeconds(sliceInfo.threadDur) /
+ tpDurationToSeconds(sliceInfo.dur);
+ const threadDurFractionSuffix = sliceInfo.threadDur === -1n ?
'' :
- ` (${(sliceInfo.threadDur / sliceInfo.dur * 100).toFixed(2)}%)`;
+ ` (${(ratio * 100).toFixed(2)}%)`;
defaultBuilder.add(
'Thread duration',
this.computeDuration(sliceInfo.threadTs, sliceInfo.threadDur) +
diff --git a/ui/src/frontend/clipboard.ts b/ui/src/frontend/clipboard.ts
index c7a27d7..38d0099 100644
--- a/ui/src/frontend/clipboard.ts
+++ b/ui/src/frontend/clipboard.ts
@@ -43,7 +43,7 @@
const line = [];
for (const col of resp.columns) {
const value = row[col];
- line.push(value === null ? 'NULL' : value.toString());
+ line.push(value === null ? 'NULL' : `${value}`);
}
lines.push(line);
}
diff --git a/ui/src/frontend/counter_panel.ts b/ui/src/frontend/counter_panel.ts
index 99d3841..4237773 100644
--- a/ui/src/frontend/counter_panel.ts
+++ b/ui/src/frontend/counter_panel.ts
@@ -14,8 +14,7 @@
import m from 'mithril';
-import {fromNs, timeToCode} from '../common/time';
-
+import {tpTimeToCode} from '../common/time';
import {globals} from './globals';
import {Panel} from './panel';
@@ -37,7 +36,11 @@
m('tr', m('th', `Name`), m('td', `${counterInfo.name}`)),
m('tr',
m('th', `Start time`),
- m('td', `${timeToCode(counterInfo.startTime)}`)),
+ m('td',
+ `${
+ tpTimeToCode(
+ counterInfo.startTime -
+ globals.state.traceTime.start)}`)),
m('tr',
m('th', `Value`),
m('td', `${counterInfo.value.toLocaleString()}`)),
@@ -46,7 +49,7 @@
m('td', `${counterInfo.delta.toLocaleString()}`)),
m('tr',
m('th', `Duration`),
- m('td', `${timeToCode(fromNs(counterInfo.duration))}`)),
+ m('td', `${tpTimeToCode(counterInfo.duration)}`)),
])],
));
} else {
diff --git a/ui/src/frontend/debug.ts b/ui/src/frontend/debug.ts
index fae7a83..7e9c9e5 100644
--- a/ui/src/frontend/debug.ts
+++ b/ui/src/frontend/debug.ts
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {produce} from 'immer';
import m from 'mithril';
import {Actions} from '../common/actions';
@@ -19,12 +20,14 @@
import {globals} from './globals';
+
declare global {
interface Window {
m: typeof m;
getSchema: typeof getSchema;
globals: typeof globals;
Actions: typeof Actions;
+ produce: typeof produce;
}
}
@@ -33,4 +36,5 @@
window.m = m;
window.globals = globals;
window.Actions = Actions;
+ window.produce = produce;
}
diff --git a/ui/src/frontend/details_panel.ts b/ui/src/frontend/details_panel.ts
index 6e5a985..e3a7585 100644
--- a/ui/src/frontend/details_panel.ts
+++ b/ui/src/frontend/details_panel.ts
@@ -17,9 +17,12 @@
import {Actions} from '../common/actions';
import {isEmptyData} from '../common/aggregation_data';
import {LogExists, LogExistsKey} from '../common/logs';
+import {pluginManager} from '../common/plugins';
import {addSelectionChangeObserver} from '../common/selection_observer';
import {Selection} from '../common/state';
import {DebugSliceDetailsTab} from '../tracks/debug/details_tab';
+import {SCROLL_JANK_PLUGIN_ID} from '../tracks/scroll_jank';
+import {TOP_LEVEL_SCROLL_KIND} from '../tracks/scroll_jank/scroll_track';
import {AggregationPanel} from './aggregation_panel';
import {ChromeSliceDetailsPanel} from './chrome_slice_panel';
@@ -45,6 +48,8 @@
const DOWN_ICON = 'keyboard_arrow_down';
const DRAG_HANDLE_HEIGHT_PX = 28;
+export const CURRENT_SELECTION_TAG = 'current_selection';
+
function getDetailsHeight() {
// This needs to be a function instead of a const to ensure the CSS constants
// have been initialized by the time we perform this calculation;
@@ -178,7 +183,7 @@
}
function handleSelectionChange(newSelection?: Selection, _?: Selection): void {
- const currentSelectionTag = 'current_selection';
+ const currentSelectionTag = CURRENT_SELECTION_TAG;
const bottomTabList = globals.bottomTabList;
if (!bottomTabList) return;
if (newSelection === undefined) {
@@ -225,6 +230,10 @@
},
});
break;
+ case TOP_LEVEL_SCROLL_KIND:
+ pluginManager.onDetailsPanelSelectionChange(
+ SCROLL_JANK_PLUGIN_ID, newSelection);
+ break;
default:
bottomTabList.closeTabByTag(currentSelectionTag);
}
diff --git a/ui/src/frontend/drag/border_drag_strategy.ts b/ui/src/frontend/drag/border_drag_strategy.ts
index df450fc..564ffc3 100644
--- a/ui/src/frontend/drag/border_drag_strategy.ts
+++ b/ui/src/frontend/drag/border_drag_strategy.ts
@@ -12,28 +12,27 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import {TimeScale} from '../time_scale';
-
import {DragStrategy} from './drag_strategy';
export class BorderDragStrategy extends DragStrategy {
private moveStart = false;
- constructor(timeScale: TimeScale, private pixelBounds: [number, number]) {
- super(timeScale);
+ constructor(map: TimeScale, private pixelBounds: [number, number]) {
+ super(map);
}
onDrag(x: number) {
- let tStart =
- this.timeScale.pxToTime(this.moveStart ? x : this.pixelBounds[0]);
- let tEnd =
- this.timeScale.pxToTime(!this.moveStart ? x : this.pixelBounds[1]);
- if (tStart > tEnd) {
+ let tStart = this.map.pxToHpTime(this.moveStart ? x : this.pixelBounds[0]);
+ let tEnd = this.map.pxToHpTime(!this.moveStart ? x : this.pixelBounds[1]);
+ if (tStart.isGreaterThan(tEnd)) {
this.moveStart = !this.moveStart;
[tEnd, tStart] = [tStart, tEnd];
}
super.updateGlobals(tStart, tEnd);
- this.pixelBounds =
- [this.timeScale.timeToPx(tStart), this.timeScale.timeToPx(tEnd)];
+ this.pixelBounds = [
+ this.map.hpTimeToPx(tStart),
+ this.map.hpTimeToPx(tEnd),
+ ];
}
onDragStart(x: number) {
diff --git a/ui/src/frontend/drag/drag_strategy.ts b/ui/src/frontend/drag/drag_strategy.ts
index 2896849..afb83e1 100644
--- a/ui/src/frontend/drag/drag_strategy.ts
+++ b/ui/src/frontend/drag/drag_strategy.ts
@@ -11,19 +11,22 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import {TimeSpan} from '../../common/time';
+import {
+ HighPrecisionTime,
+ HighPrecisionTimeSpan,
+} from '../../common/high_precision_time';
import {globals} from '../globals';
import {TimeScale} from '../time_scale';
export abstract class DragStrategy {
- constructor(protected timeScale: TimeScale) {}
+ constructor(protected map: TimeScale) {}
abstract onDrag(x: number): void;
abstract onDragStart(x: number): void;
- protected updateGlobals(tStart: number, tEnd: number) {
- const vizTime = new TimeSpan(tStart, tEnd);
+ protected updateGlobals(tStart: HighPrecisionTime, tEnd: HighPrecisionTime) {
+ const vizTime = new HighPrecisionTimeSpan(tStart, tEnd);
globals.frontendLocalState.updateVisibleTime(vizTime);
globals.rafScheduler.scheduleRedraw();
}
diff --git a/ui/src/frontend/drag/inner_drag_strategy.ts b/ui/src/frontend/drag/inner_drag_strategy.ts
index 2af1b39..7be7f7b 100644
--- a/ui/src/frontend/drag/inner_drag_strategy.ts
+++ b/ui/src/frontend/drag/inner_drag_strategy.ts
@@ -23,8 +23,8 @@
onDrag(x: number) {
const move = x - this.dragStartPx;
- const tStart = this.timeScale.pxToTime(this.pixelBounds[0] + move);
- const tEnd = this.timeScale.pxToTime(this.pixelBounds[1] + move);
+ const tStart = this.map.pxToHpTime(this.pixelBounds[0] + move);
+ const tEnd = this.map.pxToHpTime(this.pixelBounds[1] + move);
super.updateGlobals(tStart, tEnd);
}
diff --git a/ui/src/frontend/drag/outer_drag_strategy.ts b/ui/src/frontend/drag/outer_drag_strategy.ts
index 648b50d..f8269fc 100644
--- a/ui/src/frontend/drag/outer_drag_strategy.ts
+++ b/ui/src/frontend/drag/outer_drag_strategy.ts
@@ -11,16 +11,19 @@
// WITHOUT 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 {
+ HighPrecisionTime,
+} from '../../common/high_precision_time';
import {DragStrategy} from './drag_strategy';
export class OuterDragStrategy extends DragStrategy {
private dragStartPx = 0;
onDrag(x: number) {
- const dragBeginTime = this.timeScale.pxToTime(this.dragStartPx);
- const dragEndTime = this.timeScale.pxToTime(x);
- const tStart = Math.min(dragBeginTime, dragEndTime);
- const tEnd = Math.max(dragBeginTime, dragEndTime);
+ const dragBeginTime = this.map.pxToHpTime(this.dragStartPx);
+ const dragEndTime = this.map.pxToHpTime(x);
+ const tStart = HighPrecisionTime.min(dragBeginTime, dragEndTime);
+ const tEnd = HighPrecisionTime.max(dragBeginTime, dragEndTime);
super.updateGlobals(tStart, tEnd);
}
diff --git a/ui/src/frontend/drag_gesture_handler.ts b/ui/src/frontend/drag_gesture_handler.ts
index 30c0a38..4c547aa 100644
--- a/ui/src/frontend/drag_gesture_handler.ts
+++ b/ui/src/frontend/drag_gesture_handler.ts
@@ -33,8 +33,6 @@
document.body.addEventListener('mousemove', this.boundOnMouseMove);
document.body.addEventListener('mouseup', this.boundOnMouseUp);
this.pendingMouseDownEvent = e;
- // Prevent interactions with other DragGestureHandlers and event listeners
- e.stopPropagation();
}
// We don't start the drag gesture on mouse down, instead we wait until
@@ -60,17 +58,15 @@
this.onDrag(
e.clientX - this.clientRect!.left, e.clientY - this.clientRect!.top);
}
- e.stopPropagation();
}
- private onMouseUp(e: MouseEvent) {
+ private onMouseUp(_e: MouseEvent) {
this._isDragging = false;
document.body.removeEventListener('mousemove', this.boundOnMouseMove);
document.body.removeEventListener('mouseup', this.boundOnMouseUp);
if (!this.pendingMouseDownEvent) {
this.onDragFinished();
}
- e.stopPropagation();
}
get isDragging() {
diff --git a/ui/src/frontend/flamegraph_panel.ts b/ui/src/frontend/flamegraph_panel.ts
index b8246b3..0ac5f79 100644
--- a/ui/src/frontend/flamegraph_panel.ts
+++ b/ui/src/frontend/flamegraph_panel.ts
@@ -28,10 +28,9 @@
FlamegraphStateViewingOption,
ProfileType,
} from '../common/state';
-import {timeToCode} from '../common/time';
+import {tpTimeToCode} from '../common/time';
import {profileType} from '../controller/flamegraph_controller';
-import {PerfettoMouseEvent} from './events';
import {Flamegraph, NodeRendering} from './flamegraph';
import {globals} from './globals';
import {Modal, ModalDefinition} from './modal';
@@ -41,6 +40,7 @@
import {getCurrentTrace} from './sidebar';
import {convertTraceToPprofAndDownload} from './trace_converter';
import {Button} from './widgets/button';
+import {findRef} from './widgets/utils';
interface FlamegraphDetailsPanelAttrs {}
@@ -64,23 +64,24 @@
export class FlamegraphDetailsPanel extends Panel<FlamegraphDetailsPanelAttrs> {
private profileType?: ProfileType = undefined;
- private ts = 0;
+ private ts = 0n;
private pids: number[] = [];
private flamegraph: Flamegraph = new Flamegraph([]);
private focusRegex = '';
private updateFocusRegexDebounced = debounce(() => {
this.updateFocusRegex();
}, 20);
+ private canvas?: HTMLCanvasElement;
view() {
const flamegraphDetails = globals.flamegraphDetails;
if (flamegraphDetails && flamegraphDetails.type !== undefined &&
- flamegraphDetails.startNs !== undefined &&
- flamegraphDetails.durNs !== undefined &&
+ flamegraphDetails.start !== undefined &&
+ flamegraphDetails.dur !== undefined &&
flamegraphDetails.pids !== undefined &&
flamegraphDetails.upids !== undefined) {
this.profileType = profileType(flamegraphDetails.type);
- this.ts = flamegraphDetails.startNs + flamegraphDetails.durNs;
+ this.ts = flamegraphDetails.start + flamegraphDetails.dur;
this.pids = flamegraphDetails.pids;
if (flamegraphDetails.flamegraph) {
this.flamegraph.updateDataIfChanged(
@@ -91,25 +92,6 @@
0;
return m(
'.details-panel',
- {
- onclick: (e: PerfettoMouseEvent) => {
- if (this.flamegraph !== undefined) {
- this.onMouseClick({y: e.layerY, x: e.layerX});
- }
- return false;
- },
- onmousemove: (e: PerfettoMouseEvent) => {
- if (this.flamegraph !== undefined) {
- this.onMouseMove({y: e.layerY, x: e.layerX});
- globals.rafScheduler.scheduleRedraw();
- }
- },
- onmouseout: () => {
- if (this.flamegraph !== undefined) {
- this.onMouseOut();
- }
- },
- },
this.maybeShowModal(flamegraphDetails.graphIncomplete),
m('.details-panel-heading.flamegraph-profile',
{onclick: (e: MouseEvent) => e.stopPropagation()},
@@ -126,7 +108,7 @@
toSelectedCallsite(
flamegraphDetails.expandedCallsite)}`),
m('div.time',
- `Snapshot time: ${timeToCode(flamegraphDetails.durNs)}`),
+ `Snapshot time: ${tpTimeToCode(flamegraphDetails.dur)}`),
m('input[type=text][placeholder=Focus]', {
oninput: (e: Event) => {
const target = (e.target as HTMLInputElement);
@@ -146,7 +128,20 @@
}),
]),
]),
- m(`div[style=height:${height}px]`),
+ m(`canvas[ref=canvas]`, {
+ style: `height:${height}px; width:100%`,
+ onmousemove: (e: MouseEvent) => {
+ const {offsetX, offsetY} = e;
+ this.onMouseMove({x: offsetX, y: offsetY});
+ },
+ onmouseout: () => {
+ this.onMouseOut();
+ },
+ onclick: (e: MouseEvent) => {
+ const {offsetX, offsetY} = e;
+ this.onMouseClick({x: offsetX, y: offsetY});
+ },
+ }),
);
} else {
return m(
@@ -256,7 +251,53 @@
this.nodeRendering(), flamegraphData, data.expandedCallsite);
}
- renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
+ oncreate({dom}: m.CVnodeDOM<FlamegraphDetailsPanelAttrs>) {
+ this.canvas = FlamegraphDetailsPanel.findCanvasElement(dom);
+ // TODO(stevegolton): If we truely want to be standalone, then we shouldn't
+ // rely on someone else calling the rafScheduler when the window is resized,
+ // but it's good enough for now as we know the ViewerPage will do it.
+ globals.rafScheduler.addRedrawCallback(this.rafRedrawCallback);
+ }
+
+ onupdate({dom}: m.CVnodeDOM<FlamegraphDetailsPanelAttrs>) {
+ this.canvas = FlamegraphDetailsPanel.findCanvasElement(dom);
+ }
+
+ onremove(_vnode: m.CVnodeDOM<FlamegraphDetailsPanelAttrs>) {
+ globals.rafScheduler.removeRedrawCallback(this.rafRedrawCallback);
+ }
+
+ private static findCanvasElement(dom: Element): HTMLCanvasElement|undefined {
+ const canvas = findRef(dom, 'canvas');
+ if (canvas && canvas instanceof HTMLCanvasElement) {
+ return canvas;
+ } else {
+ return undefined;
+ }
+ }
+
+ private rafRedrawCallback = () => {
+ if (this.canvas) {
+ const canvas = this.canvas;
+ canvas.width = canvas.offsetWidth * devicePixelRatio;
+ canvas.height = canvas.offsetHeight * devicePixelRatio;
+ const ctx = canvas.getContext('2d');
+ if (ctx) {
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.save();
+ ctx.scale(devicePixelRatio, devicePixelRatio);
+ const {offsetWidth: width, offsetHeight: height} = canvas;
+ this.renderLocalCanvas(ctx, {width, height});
+ ctx.restore();
+ }
+ }
+ };
+
+ renderCanvas() {
+ // No-op
+ }
+
+ private renderLocalCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
this.changeFlamegraphData();
const current = globals.state.currentFlamegraphState;
if (current === null) return;
@@ -265,22 +306,24 @@
current.viewingOption === ALLOC_SPACE_MEMORY_ALLOCATED_KEY ?
'B' :
'';
- this.flamegraph.draw(ctx, size.width, size.height, 0, HEADER_HEIGHT, unit);
+ this.flamegraph.draw(ctx, size.width, size.height, 0, 0, unit);
}
- onMouseClick({x, y}: {x: number, y: number}): boolean {
+ private onMouseClick({x, y}: {x: number, y: number}): boolean {
const expandedCallsite = this.flamegraph.onMouseClick({x, y});
globals.dispatch(Actions.expandFlamegraphState({expandedCallsite}));
return true;
}
- onMouseMove({x, y}: {x: number, y: number}): boolean {
+ private onMouseMove({x, y}: {x: number, y: number}): boolean {
this.flamegraph.onMouseMove({x, y});
+ globals.rafScheduler.scheduleFullRedraw();
return true;
}
- onMouseOut() {
+ private onMouseOut() {
this.flamegraph.onMouseOut();
+ globals.rafScheduler.scheduleFullRedraw();
}
private static selectViewingOptions(profileType: ProfileType) {
diff --git a/ui/src/frontend/flow_events_renderer.ts b/ui/src/frontend/flow_events_renderer.ts
index 909dcb7..fdb91e0 100644
--- a/ui/src/frontend/flow_events_renderer.ts
+++ b/ui/src/frontend/flow_events_renderer.ts
@@ -140,7 +140,7 @@
}
private getXCoordinate(ts: number): number {
- return globals.frontendLocalState.timeScale.timeToPx(ts);
+ return globals.frontendLocalState.visibleTimeScale.secondsToPx(ts);
}
private getSliceRect(args: FlowEventsRendererArgs, point: FlowPoint):
diff --git a/ui/src/frontend/frontend_local_state.ts b/ui/src/frontend/frontend_local_state.ts
index 34663d8..f4d95ca 100644
--- a/ui/src/frontend/frontend_local_state.ts
+++ b/ui/src/frontend/frontend_local_state.ts
@@ -14,6 +14,10 @@
import {assertTrue} from '../base/logging';
import {Actions} from '../common/actions';
+import {
+ HighPrecisionTime,
+ HighPrecisionTimeSpan,
+} from '../common/high_precision_time';
import {HttpRpcState} from '../common/http_rpc_engine';
import {
Area,
@@ -21,11 +25,15 @@
Timestamped,
VisibleState,
} from '../common/state';
-import {TimeSpan} from '../common/time';
+import {Span} from '../common/time';
+import {
+ TPTime,
+ TPTimeSpan,
+} from '../common/time';
import {globals} from './globals';
import {ratelimit} from './rate_limiters';
-import {TimeScale} from './time_scale';
+import {PxSpan, TimeScale} from './time_scale';
interface Range {
start?: number;
@@ -42,10 +50,6 @@
return current;
}
-function capBetween(t: number, start: number, end: number) {
- return Math.min(Math.max(t, start), end);
-}
-
// Calculate the space a scrollbar takes up so that we can subtract it from
// the canvas width.
function calculateScrollbarWidth() {
@@ -60,13 +64,99 @@
return width;
}
+export class TimeWindow {
+ private readonly MIN_DURATION_NS = 10;
+ private _start: HighPrecisionTime = new HighPrecisionTime();
+ private _durationNanos: number = 10e9;
+
+ private get _end(): HighPrecisionTime {
+ return this._start.addNanos(this._durationNanos);
+ }
+
+ update(span: Span<HighPrecisionTime>) {
+ this._start = span.start;
+ this._durationNanos = Math.max(this.MIN_DURATION_NS, span.duration.nanos);
+ this.preventClip();
+ }
+
+ // Pan the window by certain number of seconds
+ pan(offset: HighPrecisionTime) {
+ this._start = this._start.add(offset);
+ this.preventClip();
+ }
+
+ // Zoom in or out a bit centered on a specific offset from the root
+ // Offset represents the center of the zoom as a normalized value between 0
+ // and 1 where 0 is the start of the time window and 1 is the end
+ zoom(ratio: number, offset: number) {
+ // TODO(stevegolton): Handle case where trace time < MIN_DURATION_NS
+
+ const traceDuration = globals.stateTraceTime().duration;
+ const minDuration = Math.min(this.MIN_DURATION_NS, traceDuration.nanos);
+ const newDurationNanos = Math.max(this._durationNanos * ratio, minDuration);
+ // Delta between new and old duration
+ // +ve if new duration is shorter than old duration
+ const durationDeltaNanos = this._durationNanos - newDurationNanos;
+ // If offset is 0, don't move the start at all
+ // If offset if 1, move the start by the amount the duration has changed
+ // If new duration is shorter - move start to right
+ // If new duration is longer - move start to left
+ this._start = this._start.addNanos(durationDeltaNanos * offset);
+ this._durationNanos = newDurationNanos;
+ this.preventClip();
+ }
+
+ createTimeScale(startPx: number, endPx: number): TimeScale {
+ return new TimeScale(
+ this._start, this._durationNanos, new PxSpan(startPx, endPx));
+ }
+
+ // Get timespan covering entire range of the window
+ get timeSpan(): HighPrecisionTimeSpan {
+ return new HighPrecisionTimeSpan(this._start, this._end);
+ }
+
+ get timestampSpan(): Span<TPTime> {
+ return new TPTimeSpan(this.earliest, this.latest);
+ }
+
+ get earliest(): TPTime {
+ return this._start.toTPTime('floor');
+ }
+
+ get latest(): TPTime {
+ return this._start.addNanos(this._durationNanos).toTPTime('ceil');
+ }
+
+ // Limit the zoom and pan
+ private preventClip() {
+ const traceTimeSpan = globals.stateTraceTime();
+ const traceDurationNanos = traceTimeSpan.duration.nanos;
+
+ if (this._durationNanos > traceDurationNanos) {
+ this._start = traceTimeSpan.start;
+ this._durationNanos = traceDurationNanos;
+ }
+
+ if (this._start.isLessThan(traceTimeSpan.start)) {
+ this._start = traceTimeSpan.start;
+ }
+
+ const end = this._start.addNanos(this._durationNanos);
+ if (end.isGreaterThan(traceTimeSpan.end)) {
+ this._start = traceTimeSpan.end.subtractNanos(this._durationNanos);
+ }
+ }
+}
+
/**
* State that is shared between several frontend components, but not the
* controller. This state is updated at 60fps.
*/
export class FrontendLocalState {
- visibleWindowTime = new TimeSpan(0, 10);
- timeScale = new TimeScale(this.visibleWindowTime, [0, 0]);
+ visibleWindow = new TimeWindow();
+ startPx: number = 0;
+ endPx: number = 0;
showPanningHint = false;
showCookieConsent = false;
visibleTracks = new Set<string>();
@@ -82,9 +172,9 @@
private _visibleState: VisibleState = {
lastUpdate: 0,
- startSec: 0,
- endSec: 10,
- resolution: 1,
+ start: 0n,
+ end: BigInt(10e9),
+ resolution: 1n,
};
private _selectedArea?: Area;
@@ -125,6 +215,16 @@
}
}
+ zoomVisibleWindow(ratio: number, centerPoint: number) {
+ this.visibleWindow.zoom(ratio, centerPoint);
+ this.kickUpdateLocalState();
+ }
+
+ panVisibleWindow(delta: HighPrecisionTime) {
+ this.visibleWindow.pan(delta);
+ this.kickUpdateLocalState();
+ }
+
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
@@ -137,19 +237,22 @@
this._visibleState = chooseLatest(this._visibleState, state.visibleState);
const visibleStateWasUpdated = previousVisibleState !== this._visibleState;
if (visibleStateWasUpdated) {
- this.updateLocalTime(
- new TimeSpan(this._visibleState.startSec, this._visibleState.endSec));
+ this.updateLocalTime(new HighPrecisionTimeSpan(
+ HighPrecisionTime.fromTPTime(this._visibleState.start),
+ HighPrecisionTime.fromTPTime(this._visibleState.end),
+ ));
}
}
+ // Set the highlight box to draw
selectArea(
- startSec: number, endSec: number,
+ start: TPTime, end: TPTime,
tracks = this._selectedArea ? this._selectedArea.tracks : []) {
assertTrue(
- endSec >= startSec,
- `Impossible select area: startSec [${startSec}] >= endSec [${endSec}]`);
+ end >= start,
+ `Impossible select area: start [${start}] >= end [${end}]`);
this.showPanningHint = true;
- this._selectedArea = {startSec, endSec, tracks};
+ this._selectedArea = {start, end, tracks},
globals.rafScheduler.scheduleFullRedraw();
}
@@ -166,12 +269,11 @@
globals.dispatch(Actions.setVisibleTraceTime(this._visibleState));
}, 50);
- private updateLocalTime(ts: TimeSpan) {
- const traceTime = globals.state.traceTime;
- const startSec = capBetween(ts.start, traceTime.startSec, traceTime.endSec);
- const endSec = capBetween(ts.end, traceTime.startSec, traceTime.endSec);
- this.visibleWindowTime = new TimeSpan(startSec, endSec);
- this.timeScale.setTimeBounds(this.visibleWindowTime);
+ private updateLocalTime(ts: Span<HighPrecisionTime>) {
+ const traceBounds = globals.stateTraceTime();
+ const start = ts.start.clamp(traceBounds.start, traceBounds.end);
+ const end = ts.end.clamp(traceBounds.start, traceBounds.end);
+ this.visibleWindow.update(new HighPrecisionTimeSpan(start, end));
this.updateResolution();
}
@@ -181,17 +283,17 @@
this.ratelimitedUpdateVisible();
}
- updateVisibleTime(ts: TimeSpan) {
- this.updateLocalTime(ts);
+ private kickUpdateLocalState() {
this._visibleState.lastUpdate = Date.now() / 1000;
- this._visibleState.startSec = this.visibleWindowTime.start;
- this._visibleState.endSec = this.visibleWindowTime.end;
+ this._visibleState.start = this.visibleWindowTime.start.toTPTime();
+ this._visibleState.end = this.visibleWindowTime.end.toTPTime();
this._visibleState.resolution = globals.getCurResolution();
this.ratelimitedUpdateVisible();
}
- getVisibleStateBounds(): [number, number] {
- return [this.visibleWindowTime.start, this.visibleWindowTime.end];
+ updateVisibleTime(ts: Span<HighPrecisionTime>) {
+ this.updateLocalTime(ts);
+ this.kickUpdateLocalState();
}
// Whenever start/end px of the timeScale is changed, update
@@ -202,7 +304,28 @@
pxStart = Math.max(0, pxStart);
pxEnd = Math.max(0, pxEnd);
if (pxStart === pxEnd) pxEnd = pxStart + 1;
- this.timeScale.setLimitsPx(pxStart, pxEnd);
+ this.startPx = pxStart;
+ this.endPx = pxEnd;
this.updateResolution();
}
+
+ // Get the time scale for the visible window
+ get visibleTimeScale(): TimeScale {
+ return this.visibleWindow.createTimeScale(this.startPx, this.endPx);
+ }
+
+ // Produces a TimeScale object for this time window provided start and end px
+ getTimeScale(startPx: number, endPx: number): TimeScale {
+ return this.visibleWindow.createTimeScale(startPx, endPx);
+ }
+
+ // Get the bounds of the window in pixels
+ get windowSpan(): PxSpan {
+ return new PxSpan(this.startPx, this.endPx);
+ }
+
+ // Get the bounds of the visible time window as a time span
+ get visibleWindowTime(): Span<HighPrecisionTime> {
+ return this.visibleWindow.timeSpan;
+ }
}
diff --git a/ui/src/frontend/ftrace_panel.ts b/ui/src/frontend/ftrace_panel.ts
index 8de83cb..e45b5fe 100644
--- a/ui/src/frontend/ftrace_panel.ts
+++ b/ui/src/frontend/ftrace_panel.ts
@@ -18,7 +18,7 @@
import {assertExists} from '../base/logging';
import {Actions} from '../common/actions';
import {colorForString} from '../common/colorizer';
-import {formatTimestamp} from '../common/time';
+import {formatTPTime, TPTime} from '../common/time';
import {globals} from './globals';
import {Panel} from './panel';
@@ -117,12 +117,12 @@
this.recomputeVisibleRowsAndUpdate(scrollContainer);
};
- onRowOver(ts: number) {
+ onRowOver(ts: TPTime) {
globals.dispatch(Actions.setHoverCursorTimestamp({ts}));
}
onRowOut() {
- globals.dispatch(Actions.setHoverCursorTimestamp({ts: -1}));
+ globals.dispatch(Actions.setHoverCursorTimestamp({ts: -1n}));
}
private renderRowsLabel() {
@@ -188,8 +188,7 @@
for (let i = 0; i < events.length; i++) {
const {ts, name, cpu, process, args} = events[i];
- const timestamp =
- formatTimestamp(ts / 1e9 - globals.state.traceTime.startSec);
+ const timestamp = formatTPTime(ts - globals.state.traceTime.start);
const rank = i + offset;
@@ -204,7 +203,7 @@
`.row`,
{
style: {top: `${(rank + 1.0) * ROW_H}px`},
- onmouseover: this.onRowOver.bind(this, ts / 1e9),
+ onmouseover: this.onRowOver.bind(this, ts),
onmouseout: this.onRowOut.bind(this),
},
m('.cell', timestamp),
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 0ca10a0..79ca58a 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {BigintMath} from '../base/bigint_math';
import {assertExists} from '../base/logging';
import {Actions, DeferredAction} from '../common/actions';
import {AggregateData} from '../common/aggregation_data';
@@ -22,10 +23,19 @@
} from '../common/conversion_jobs';
import {createEmptyState} from '../common/empty_state';
import {Engine} from '../common/engine';
+import {
+ HighPrecisionTime,
+ HighPrecisionTimeSpan,
+} from '../common/high_precision_time';
import {MetricResult} from '../common/metric_data';
import {CurrentSearchResults, SearchSummary} from '../common/search_data';
import {CallsiteInfo, EngineConfig, ProfileType, State} from '../common/state';
-import {fromNs, toNs} from '../common/time';
+import {Span, tpTimeFromSeconds} from '../common/time';
+import {
+ TPDuration,
+ TPTime,
+ TPTimeSpan,
+} from '../common/time';
import {Analytics, initAnalytics} from './analytics';
import {BottomTabList} from './bottom_tab';
@@ -33,6 +43,7 @@
import {RafScheduler} from './raf_scheduler';
import {Router} from './router';
import {ServiceWorkerController} from './service_worker_controller';
+import {PxSpan, TimeScale} from './time_scale';
type Dispatch = (action: DeferredAction) => void;
type TrackDataStore = Map<string, {}>;
@@ -41,18 +52,18 @@
type Description = Map<string, string>;
export interface SliceDetails {
- ts?: number;
+ ts?: TPTime;
absTime?: string;
- dur?: number;
- threadTs?: number;
- threadDur?: number;
+ dur?: TPDuration;
+ threadTs?: TPTime;
+ threadDur?: TPDuration;
priority?: number;
endState?: string|null;
cpu?: number;
id?: number;
threadStateId?: number;
utid?: number;
- wakeupTs?: number;
+ wakeupTs?: TPTime;
wakerUtid?: number;
wakerCpu?: number;
category?: string;
@@ -104,23 +115,23 @@
}
export interface CounterDetails {
- startTime?: number;
+ startTime?: TPTime;
value?: number;
delta?: number;
- duration?: number;
+ duration?: TPDuration;
name?: string;
}
export interface ThreadStateDetails {
- ts?: number;
- dur?: number;
+ ts?: TPTime;
+ dur?: TPDuration;
}
export interface FlamegraphDetails {
type?: ProfileType;
id?: number;
- startNs?: number;
- durNs?: number;
+ start?: TPTime;
+ dur?: TPDuration;
pids?: number[];
upids?: number[];
flamegraph?: CallsiteInfo[];
@@ -143,8 +154,8 @@
}
export interface QuantizedLoad {
- startSec: number;
- endSec: number;
+ start: TPTime;
+ end: TPTime;
load: number;
}
type OverviewStore = Map<string, QuantizedLoad[]>;
@@ -161,7 +172,7 @@
export interface FtraceEvent {
id: number;
- ts: number;
+ ts: TPTime;
name: string;
cpu: number;
thread: string|null;
@@ -530,7 +541,7 @@
this.aggregateDataStore.set(kind, data);
}
- getCurResolution() {
+ getCurResolution(): TPDuration {
// Truncate the resolution to the closest power of 2 (in nanosecond space).
// We choose to work in ns space because resolution is consumed be track
// controllers for quantization and they rely on resolution to be a power
@@ -541,24 +552,18 @@
// levels. Logic: each zoom level represents a delta of 0.1 * (visible
// window span). Therefore, zooming out by six levels is 1.1^6 ~= 2.
// Similarily, zooming in six levels is 0.9^6 ~= 0.5.
- const pxToSec = this.frontendLocalState.timeScale.deltaPxToDuration(1);
+ const timeScale = this.frontendLocalState.visibleTimeScale;
// TODO(b/186265930): Remove once fixed:
- if (!isFinite(pxToSec)) {
- // Resolution is in pixels per second so 1000 means 1px = 1ms.
- console.error(`b/186265930: Bad pxToSec suppressed ${pxToSec}`);
- return fromNs(Math.pow(2, Math.floor(Math.log2(toNs(1000)))));
+ if (timeScale.pxSpan.delta === 0) {
+ console.error(`b/186265930: Bad pxToSec suppressed`);
+ return BigintMath.bitFloor(tpTimeFromSeconds(1000));
}
- const pxToNs = Math.max(toNs(pxToSec), 1);
- const resolution = fromNs(Math.pow(2, Math.floor(Math.log2(pxToNs))));
- const log2 = Math.log2(toNs(resolution));
- if (log2 % 1 !== 0) {
- throw new Error(`Resolution should be a power of two.
- pxToSec: ${pxToSec},
- pxToNs: ${pxToNs},
- resolution: ${resolution},
- log2: ${Math.log2(toNs(resolution))}`);
- }
- return resolution;
+
+ const timePerPx = HighPrecisionTime.max(
+ timeScale.pxDeltaToDuration(1), new HighPrecisionTime(1n));
+
+ const resolutionBig = BigintMath.bitFloor(timePerPx.toTPTime());
+ return resolutionBig;
}
getCurrentEngine(): EngineConfig|undefined {
@@ -637,6 +642,30 @@
shutdown() {
this._rafScheduler!.shutdown();
}
+
+ // Get a timescale that covers the entire trace
+ getTraceTimeScale(pxSpan: PxSpan): TimeScale {
+ const {start, end} = this.state.traceTime;
+ const traceTime = HighPrecisionTimeSpan.fromTpTime(start, end);
+ return new TimeScale(traceTime.start, traceTime.duration.nanos, pxSpan);
+ }
+
+ // Get the trace time bounds
+ stateTraceTime(): Span<HighPrecisionTime> {
+ const {start, end} = this.state.traceTime;
+ return HighPrecisionTimeSpan.fromTpTime(start, end);
+ }
+
+ stateTraceTimeTP(): Span<TPTime> {
+ const {start, end} = this.state.traceTime;
+ return new TPTimeSpan(start, end);
+ }
+
+ // Get the state version of the visible time bounds
+ stateVisibleTime(): Span<TPTime> {
+ const {start, end} = this.state.frontendLocalState.visibleState;
+ return new TPTimeSpan(start, end);
+ }
}
export const globals = new Globals();
diff --git a/ui/src/frontend/gridline_helper.ts b/ui/src/frontend/gridline_helper.ts
index 1c9dbfe..6581c81 100644
--- a/ui/src/frontend/gridline_helper.ts
+++ b/ui/src/frontend/gridline_helper.ts
@@ -13,49 +13,91 @@
// limitations under the License.
import {assertTrue} from '../base/logging';
-import {roundDownNearest} from '../base/math_utils';
+import {Span, tpDurationToSeconds} from '../common/time';
+import {TPDuration, TPTime, TPTimeSpan} from '../common/time';
+
import {TRACK_BORDER_COLOR, TRACK_SHELL_WIDTH} from './css_constants';
import {globals} from './globals';
import {TimeScale} from './time_scale';
-// Returns the optimal step size (in seconds) and tick pattern of ticks within
-// the step. The returned step size has two properties: (1) It is 1, 2, or 5,
-// multiplied by some integer power of 10. (2) It is maximised given the
-// constraint: |range| / stepSize <= |maxNumberOfSteps|.
-export function getStepSize(
- range: number, maxNumberOfSteps: number): [number, string] {
- // First, get the largest possible power of 10 that is smaller than the
- // desired step size, and use it as our initial step size.
- // For example, if the range is 2345ms and the desired steps is 10, then the
- // minimum step size is 234.5ms so the step size will initialise to 100.
- const minStepSize = range / maxNumberOfSteps;
- const zeros = Math.floor(Math.log10(minStepSize));
- const initialStepSize = Math.pow(10, zeros);
+const micros = 1000n;
+const millis = 1000n * micros;
+const seconds = 1000n * millis;
+const minutes = 60n * seconds;
+const hours = 60n * minutes;
+const days = 24n * hours;
- // We know that |initialStepSize| is a power of 10, and
- // initialStepSize <= desiredStepSize <= 10 * initialStepSize. There are four
- // possible candidates for final step size: 1, 2, 5 or 10 * initialStepSize.
- // For our example above, this would result in a step size of 500ms, as both
- // 100ms and 200ms are smaller than the minimum step size of 234.5ms.
- // We pick the candidate that minimizes the step size without letting the
- // number of steps exceed |maxNumberOfSteps|. The factor we pick to also
- // determines the pattern of ticks. This pattern is represented using a string
- // where:
- // | = Major tick
- // : = Medium tick
- // . = Minor tick
- const stepSizeMultipliers: [number, string][] =
- [[1, '|....:....'], [2, '|.:.'], [5, '|....'], [10, '|....:....']];
+// These patterns cover the entire range of 0 - 2^63-1 nanoseconds
+const patterns: [bigint, string][] = [
+ [1n, '|'],
+ [2n, '|:'],
+ [5n, '|....'],
+ [10n, '|....:....'],
+ [20n, '|.:.'],
+ [50n, '|....'],
+ [100n, '|....:....'],
+ [200n, '|.:.'],
+ [500n, '|....'],
+ [1n * micros, '|....:....'],
+ [2n * micros, '|.:.'],
+ [5n * micros, '|....'],
+ [10n * micros, '|....:....'],
+ [20n * micros, '|.:.'],
+ [50n * micros, '|....'],
+ [100n * micros, '|....:....'],
+ [200n * micros, '|.:.'],
+ [500n * micros, '|....'],
+ [1n * millis, '|....:....'],
+ [2n * millis, '|.:.'],
+ [5n * millis, '|....'],
+ [10n * millis, '|....:....'],
+ [20n * millis, '|.:.'],
+ [50n * millis, '|....'],
+ [100n * millis, '|....:....'],
+ [200n * millis, '|.:.'],
+ [500n * millis, '|....'],
+ [1n * seconds, '|....:....'],
+ [2n * seconds, '|.:.'],
+ [5n * seconds, '|....'],
+ [10n * seconds, '|....:....'],
+ [30n * seconds, '|.:.:.'],
+ [1n * minutes, '|.....'],
+ [2n * minutes, '|.:.'],
+ [5n * minutes, '|.....'],
+ [10n * minutes, '|....:....'],
+ [30n * minutes, '|.:.:.'],
+ [1n * hours, '|.....'],
+ [2n * hours, '|.:.'],
+ [6n * hours, '|.....'],
+ [12n * hours, '|.....:.....'],
+ [1n * days, '|.:.'],
+ [2n * days, '|.:.'],
+ [5n * days, '|....'],
+ [10n * days, '|....:....'],
+ [20n * days, '|.:.'],
+ [50n * days, '|....'],
+ [100n * days, '|....:....'],
+ [200n * days, '|.:.'],
+ [500n * days, '|....'],
+ [1000n * days, '|....:....'],
+ [2000n * days, '|.:.'],
+ [5000n * days, '|....'],
+ [10000n * days, '|....:....'],
+ [20000n * days, '|.:.'],
+ [50000n * days, '|....'],
+ [100000n * days, '|....:....'],
+ [200000n * days, '|.:.'],
+];
- for (const [multiplier, pattern] of stepSizeMultipliers) {
- const newStepSize = multiplier * initialStepSize;
- const numberOfNewSteps = range / newStepSize;
- if (numberOfNewSteps <= maxNumberOfSteps) {
- return [newStepSize, pattern];
+// Returns the optimal step size and pattern of ticks within the step.
+export function getPattern(minPatternSize: bigint): [TPDuration, string] {
+ for (const [size, pattern] of patterns) {
+ if (size >= minPatternSize) {
+ return [size, pattern];
}
}
- throw new Error('Something has gone horribly wrong with maths');
+ throw new Error('Pattern not defined for this minsize');
}
function tickPatternToArray(pattern: string): TickType[] {
@@ -75,21 +117,23 @@
});
}
-// Assuming a number only has one non-zero decimal digit, find the number of
-// decimal places required to accurately print that number. I.e. the parameter
-// we should pass to number.toFixed(x). To account for floating point
-// innaccuracies when representing numbers in base-10, we only take the first
-// nonzero fractional digit into account. E.g.
+// Get the number of decimal places we would have to print a time to for a given
+// min step size. For example, if we know the min step size is 0.1 and all
+// values are going to be aligned to integral multiples of 0.1, there's no
+// point printing these values with more than 1 decimal place.
+// Note: It's assumed that stepSize only has one significant figure.
+// E.g. 0.3 and 0.00002 are fine, but 0.123 will be treated as if it were 0.1.
+// Some examples: (seconds -> decimal places)
// 1.0 -> 0
// 0.5 -> 1
// 0.009 -> 3
// 0.00007 -> 5
// 30000 -> 0
// 0.30000000000000004 -> 1
-export function guessDecimalPlaces(val: number): number {
- const neglog10 = -Math.floor(Math.log10(val));
- const clamped = Math.max(0, neglog10);
- return clamped;
+export function guessDecimalPlaces(stepSize: TPDuration): number {
+ const stepSizeSeconds = tpDurationToSeconds(stepSize);
+ const decimalPlaces = -Math.floor(Math.log10(stepSizeSeconds));
+ return Math.max(0, decimalPlaces);
}
export enum TickType {
@@ -100,55 +144,58 @@
export interface Tick {
type: TickType;
- time: number;
- position: number;
+ time: TPTime;
}
const MIN_PX_PER_STEP = 80;
+export function getMaxMajorTicks(width: number) {
+ return Math.max(1, Math.floor(width / MIN_PX_PER_STEP));
+}
+
+function roundDownNearest(time: TPTime, stepSize: TPDuration): TPTime {
+ return stepSize * (time / stepSize);
+}
// An iterable which generates a series of ticks for a given timescale.
export class TickGenerator implements Iterable<Tick> {
private _tickPattern: TickType[];
- private _patternSize: number;
+ private _patternSize: TPDuration;
+ private _timeSpan: Span<TPTime>;
+ private _offset: TPTime;
- constructor(private scale: TimeScale, {minLabelPx = MIN_PX_PER_STEP} = {}) {
- assertTrue(minLabelPx > 0, 'minLabelPx cannot be lte 0');
- assertTrue(scale.widthPx > 0, 'widthPx cannot be lte 0');
- assertTrue(
- scale.timeSpan.duration > 0, 'timeSpan.duration cannot be lte 0');
+ constructor(
+ timeSpan: Span<TPTime>, maxMajorTicks: number, offset: TPTime = 0n) {
+ assertTrue(timeSpan.duration > 0n, 'timeSpan.duration cannot be lte 0');
+ assertTrue(maxMajorTicks > 0, 'maxMajorTicks cannot be lte 0');
- const desiredSteps = scale.widthPx / minLabelPx;
- const [size, pattern] = getStepSize(scale.timeSpan.duration, desiredSteps);
+ this._timeSpan = timeSpan.add(-offset);
+ this._offset = offset;
+ const minStepSize =
+ BigInt(Math.floor(Number(timeSpan.duration) / maxMajorTicks));
+ const [size, pattern] = getPattern(minStepSize);
this._patternSize = size;
this._tickPattern = tickPatternToArray(pattern);
}
// Returns an iterable, so this object can be iterated over directly using the
// `for x of y` notation. The use of a generator here is just to make things
- // more elegant than creating an array of ticks and building an iterator for
- // it.
+ // more elegant compared to creating an array of ticks and building an
+ // iterator for it.
* [Symbol.iterator](): Generator<Tick> {
- const span = this.scale.timeSpan;
- const stepSize = this._patternSize / this._tickPattern.length;
- const start = roundDownNearest(span.start, this._patternSize);
- const timeAtStep = (i: number) => start + (i * stepSize);
+ const stepSize = this._patternSize / BigInt(this._tickPattern.length);
+ const start = roundDownNearest(this._timeSpan.start, this._patternSize);
+ const end = this._timeSpan.end;
+ let patternIndex = 0;
- // Iterating using steps instead of
- // for (let s = start; s < span.end; s += stepSize) because if start is much
- // larger than stepSize we can enter an infinite loop due to floating
- // point precision errors.
- for (let i = 0; timeAtStep(i) < span.end; i++) {
- const time = timeAtStep(i);
- if (time >= span.start) {
- const position = Math.floor(this.scale.timeToPx(time));
- const type = this._tickPattern[i % this._tickPattern.length];
- yield {type, time, position};
+ for (let time = start; time < end; time += stepSize, patternIndex++) {
+ if (time >= this._timeSpan.start) {
+ patternIndex = patternIndex % this._tickPattern.length;
+ const type = this._tickPattern[patternIndex];
+ yield {type, time: time + this._offset};
}
}
}
- // The number of decimal places labels should be printed with, assuming labels
- // are only printed on major ticks.
get digits(): number {
return guessDecimalPlaces(this._patternSize);
}
@@ -157,9 +204,7 @@
// Gets the timescale associated with the current visible window.
export function timeScaleForVisibleWindow(
startPx: number, endPx: number): TimeScale {
- const span = globals.frontendLocalState.visibleWindowTime;
- const spanRelative = span.add(-globals.state.traceTime.startSec);
- return new TimeScale(spanRelative, [startPx, endPx]);
+ return globals.frontendLocalState.getTimeScale(startPx, endPx);
}
export function drawGridLines(
@@ -169,13 +214,18 @@
ctx.strokeStyle = TRACK_BORDER_COLOR;
ctx.lineWidth = 1;
- const timeScale = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, width);
- if (timeScale.timeSpan.duration > 0 && timeScale.widthPx > 0) {
- for (const {type, position} of new TickGenerator(timeScale)) {
+ const {earliest, latest} = globals.frontendLocalState.visibleWindow;
+ const span = new TPTimeSpan(earliest, latest);
+ if (width > TRACK_SHELL_WIDTH && span.duration > 0n) {
+ const maxMajorTicks = getMaxMajorTicks(width - TRACK_SHELL_WIDTH);
+ const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, width);
+ for (const {type, time} of new TickGenerator(
+ span, maxMajorTicks, globals.state.traceTime.start)) {
+ const px = Math.floor(map.tpTimeToPx(time));
if (type === TickType.MAJOR) {
ctx.beginPath();
- ctx.moveTo(position + 0.5, 0);
- ctx.lineTo(position + 0.5, height);
+ ctx.moveTo(px + 0.5, 0);
+ ctx.lineTo(px + 0.5, height);
ctx.stroke();
}
}
diff --git a/ui/src/frontend/gridline_helper_unittest.ts b/ui/src/frontend/gridline_helper_unittest.ts
index 3b6dcac..2454680 100644
--- a/ui/src/frontend/gridline_helper_unittest.ts
+++ b/ui/src/frontend/gridline_helper_unittest.ts
@@ -12,303 +12,93 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {TimeSpan} from '../common/time';
+import {TPTimeSpan} from '../common/time';
-import {getStepSize, Tick, TickGenerator, TickType} from './gridline_helper';
-import {TimeScale} from './time_scale';
-
-const pattern1 = '|....:....';
-const pattern2 = '|.:.';
-const pattern5 = '|....';
-const timeScale = new TimeScale(new TimeSpan(0, 1), [1, 2]);
+import {getPattern, TickGenerator, TickType} from './gridline_helper';
test('gridline helper to have sensible step sizes', () => {
- expect(getStepSize(10, 14)).toEqual([1, pattern1]);
- expect(getStepSize(30, 14)).toEqual([5, pattern5]);
- expect(getStepSize(60, 14)).toEqual([5, pattern5]);
- expect(getStepSize(100, 14)).toEqual([10, pattern1]);
+ expect(getPattern(1n)).toEqual([1n, '|']);
+ expect(getPattern(2n)).toEqual([2n, '|:']);
+ expect(getPattern(3n)).toEqual([5n, '|....']);
+ expect(getPattern(4n)).toEqual([5n, '|....']);
+ expect(getPattern(5n)).toEqual([5n, '|....']);
+ expect(getPattern(7n)).toEqual([10n, '|....:....']);
- expect(getStepSize(10, 21)).toEqual([0.5, pattern5]);
- expect(getStepSize(30, 21)).toEqual([2, pattern2]);
- expect(getStepSize(60, 21)).toEqual([5, pattern5]);
- expect(getStepSize(100, 21)).toEqual([5, pattern5]);
+ expect(getPattern(10n)).toEqual([10n, '|....:....']);
+ expect(getPattern(20n)).toEqual([20n, '|.:.']);
+ expect(getPattern(50n)).toEqual([50n, '|....']);
- expect(getStepSize(10, 3)).toEqual([5, pattern5]);
- expect(getStepSize(30, 3)).toEqual([10, pattern1]);
- expect(getStepSize(60, 3)).toEqual([20, pattern2]);
- expect(getStepSize(100, 3)).toEqual([50, pattern5]);
-
- expect(getStepSize(800, 4)).toEqual([200, pattern2]);
+ expect(getPattern(100n)).toEqual([100n, '|....:....']);
});
-test('gridline helper to scale to very small and very large values', () => {
- expect(getStepSize(.01, 14)).toEqual([.001, pattern1]);
- expect(getStepSize(10000, 14)).toEqual([1000, pattern1]);
-});
+describe('TickGenerator', () => {
+ it('can generate ticks with span starting at origin', () => {
+ const tickGen = new TickGenerator(new TPTimeSpan(0n, 10n), 1);
+ const expected = [
+ {type: TickType.MAJOR, time: 0n},
+ {type: TickType.MINOR, time: 1n},
+ {type: TickType.MINOR, time: 2n},
+ {type: TickType.MINOR, time: 3n},
+ {type: TickType.MINOR, time: 4n},
+ {type: TickType.MEDIUM, time: 5n},
+ {type: TickType.MINOR, time: 6n},
+ {type: TickType.MINOR, time: 7n},
+ {type: TickType.MINOR, time: 8n},
+ {type: TickType.MINOR, time: 9n},
+ ];
+ const actual = Array.from(tickGen!);
+ expect(actual).toStrictEqual(expected);
+ expect(tickGen!.digits).toEqual(8);
+ });
-test('gridline helper to always return a reasonable number of steps', () => {
- for (let i = 1; i <= 1000; i++) {
- const [stepSize, _] = getStepSize(i, 14);
- expect(Math.round(i / stepSize)).toBeGreaterThanOrEqual(6);
- expect(Math.round(i / stepSize)).toBeLessThanOrEqual(14);
- }
-});
+ it('can generate ticks when span has an offset', () => {
+ const tickGen = new TickGenerator(new TPTimeSpan(10n, 20n), 1);
+ const expected = [
+ {type: TickType.MAJOR, time: 10n},
+ {type: TickType.MINOR, time: 11n},
+ {type: TickType.MINOR, time: 12n},
+ {type: TickType.MINOR, time: 13n},
+ {type: TickType.MINOR, time: 14n},
+ {type: TickType.MEDIUM, time: 15n},
+ {type: TickType.MINOR, time: 16n},
+ {type: TickType.MINOR, time: 17n},
+ {type: TickType.MINOR, time: 18n},
+ {type: TickType.MINOR, time: 19n},
+ ];
+ const actual = Array.from(tickGen!);
+ expect(actual).toStrictEqual(expected);
+ expect(tickGen!.digits).toEqual(8);
+ });
-describe('TickGenerator with range 0.0-1.0 and room for 2 labels', () => {
- let tickGen: TickGenerator|undefined = undefined;
- beforeAll(() => {
- const timeSpan = new TimeSpan(0.0, 1.0);
- const timeScale = new TimeScale(timeSpan, [0, 200]);
- tickGen = new TickGenerator(timeScale, {minLabelPx: 100});
- });
- it('should produce major ticks at 0.5s and minor ticks at 0.1s starting at 0',
- () => {
- const expected = [
- {type: TickType.MAJOR, time: 0.0},
- {type: TickType.MINOR, time: 0.1},
- {type: TickType.MINOR, time: 0.2},
- {type: TickType.MINOR, time: 0.3},
- {type: TickType.MINOR, time: 0.4},
- {type: TickType.MAJOR, time: 0.5},
- {type: TickType.MINOR, time: 0.6},
- {type: TickType.MINOR, time: 0.7},
- {type: TickType.MINOR, time: 0.8},
- {type: TickType.MINOR, time: 0.9},
- ];
- const actual = Array.from(tickGen!);
- expectTicksEqual(actual, expected);
- });
- it('should tell us to use 1 decimal place for labels', () => {
- expect(tickGen!.digits).toEqual(1);
- });
-});
-
-describe('TickGenerator with range 0.3-1.3 and room for 2 labels', () => {
- let tickGen: TickGenerator|undefined = undefined;
- beforeAll(() => {
- const timeSpan = new TimeSpan(0.3, 1.3);
- const timeScale = new TimeScale(timeSpan, [0, 200]);
- tickGen = new TickGenerator(timeScale, {minLabelPx: 100});
- });
- it('should produce major ticks at 0.5s and minor ticks at 0.1s starting at 0',
- () => {
- const expected = [
- {type: TickType.MINOR, time: 0.3},
- {type: TickType.MINOR, time: 0.4},
- {type: TickType.MAJOR, time: 0.5},
- {type: TickType.MINOR, time: 0.6},
- {type: TickType.MINOR, time: 0.7},
- {type: TickType.MINOR, time: 0.8},
- {type: TickType.MINOR, time: 0.9},
- {type: TickType.MAJOR, time: 1.0},
- {type: TickType.MINOR, time: 1.1},
- {type: TickType.MINOR, time: 1.2},
- ];
- const actual = Array.from(tickGen!);
- expectTicksEqual(actual, expected);
- });
- it('should tell us to use 1 decimal place for labels', () => {
- expect(tickGen!.digits).toEqual(1);
- });
-});
-
-describe('TickGenerator with range 0.0-0.2 and room for 1 label', () => {
- let tickGen: TickGenerator|undefined = undefined;
- beforeAll(() => {
- const timeSpan = new TimeSpan(0.0, 0.2);
- const timeScale = new TimeScale(timeSpan, [0, 100]);
- tickGen = new TickGenerator(timeScale, {minLabelPx: 100});
- });
- it('should produce major ticks at 0.2s and minor ticks at 0.1s starting at 0',
- () => {
- const expected = [
- {type: TickType.MAJOR, time: 0.0},
- {type: TickType.MINOR, time: 0.05},
- {type: TickType.MEDIUM, time: 0.1},
- {type: TickType.MINOR, time: 0.15},
- ];
- const actual = Array.from(tickGen!);
- expectTicksEqual(actual, expected);
- });
- it('should tell us to use 1 decimal place for labels', () => {
- expect(tickGen!.digits).toEqual(1);
- });
-});
-
-describe('TickGenerator with range 0.0-0.1 and room for 1 label', () => {
- let tickGen: TickGenerator|undefined = undefined;
- beforeAll(() => {
- const timeSpan = new TimeSpan(0.0, 0.1);
- const timeScale = new TimeScale(timeSpan, [0, 100]);
- tickGen = new TickGenerator(timeScale, {minLabelPx: 100});
- });
- it('should produce major ticks at 0.1s & minor ticks at 0.02s starting at 0',
- () => {
- const expected = [
- {type: TickType.MAJOR, time: 0.0},
- {type: TickType.MINOR, time: 0.01},
- {type: TickType.MINOR, time: 0.02},
- {type: TickType.MINOR, time: 0.03},
- {type: TickType.MINOR, time: 0.04},
- {type: TickType.MEDIUM, time: 0.05},
- {type: TickType.MINOR, time: 0.06},
- {type: TickType.MINOR, time: 0.07},
- {type: TickType.MINOR, time: 0.08},
- {type: TickType.MINOR, time: 0.09},
- ];
- const actual = Array.from(tickGen!);
- expect(tickGen!.digits).toEqual(1);
- expectTicksEqual(actual, expected);
- });
- it('should tell us to use 1 decimal place for labels', () => {
- expect(tickGen!.digits).toEqual(1);
- });
-});
-
-describe('TickGenerator with a very small timespan', () => {
- let tickGen: TickGenerator|undefined = undefined;
- beforeAll(() => {
- const timeSpan = new TimeSpan(0.0, 1e-9);
- const timeScale = new TimeScale(timeSpan, [0, 100]);
- tickGen = new TickGenerator(timeScale, {minLabelPx: 100});
- });
- it('should generate minor ticks at 2e-10s and one major tick at the start',
- () => {
- const expected = [
- {type: TickType.MAJOR, time: 0.0},
- {type: TickType.MINOR, time: 1e-10},
- {type: TickType.MINOR, time: 2e-10},
- {type: TickType.MINOR, time: 3e-10},
- {type: TickType.MINOR, time: 4e-10},
- {type: TickType.MEDIUM, time: 5e-10},
- {type: TickType.MINOR, time: 6e-10},
- {type: TickType.MINOR, time: 7e-10},
- {type: TickType.MINOR, time: 8e-10},
- {type: TickType.MINOR, time: 9e-10},
- ];
- const actual = Array.from(tickGen!);
- expectTicksEqual(actual, expected);
- });
- it('should tell us to use 9 decimal places for labels', () => {
- expect(tickGen!.digits).toEqual(9);
- });
-});
-
-describe('TickGenerator with a very large timespan', () => {
- let tickGen: TickGenerator|undefined = undefined;
- beforeAll(() => {
- const timeSpan = new TimeSpan(0.0, 1e9);
- const timeScale = new TimeScale(timeSpan, [0, 100]);
- tickGen = new TickGenerator(timeScale, {minLabelPx: 100});
- });
- it('should generate minor ticks at 2e8 and one major tick at the start',
- () => {
- const expected = [
- {type: TickType.MAJOR, time: 0.0},
- {type: TickType.MINOR, time: 1e8},
- {type: TickType.MINOR, time: 2e8},
- {type: TickType.MINOR, time: 3e8},
- {type: TickType.MINOR, time: 4e8},
- {type: TickType.MEDIUM, time: 5e8},
- {type: TickType.MINOR, time: 6e8},
- {type: TickType.MINOR, time: 7e8},
- {type: TickType.MINOR, time: 8e8},
- {type: TickType.MINOR, time: 9e8},
- ];
- const actual = Array.from(tickGen!);
- expectTicksEqual(actual, expected);
- });
- it('should tell us to use 0 decimal places for labels', () => {
+ it('can generate ticks when span is large', () => {
+ const tickGen =
+ new TickGenerator(new TPTimeSpan(1000000000n, 2000000000n), 1);
+ const expected = [
+ {type: TickType.MAJOR, time: 1000000000n},
+ {type: TickType.MINOR, time: 1100000000n},
+ {type: TickType.MINOR, time: 1200000000n},
+ {type: TickType.MINOR, time: 1300000000n},
+ {type: TickType.MINOR, time: 1400000000n},
+ {type: TickType.MEDIUM, time: 1500000000n},
+ {type: TickType.MINOR, time: 1600000000n},
+ {type: TickType.MINOR, time: 1700000000n},
+ {type: TickType.MINOR, time: 1800000000n},
+ {type: TickType.MINOR, time: 1900000000n},
+ ];
+ const actual = Array.from(tickGen!);
+ expect(actual).toStrictEqual(expected);
expect(tickGen!.digits).toEqual(0);
});
-});
-describe('TickGenerator where the timespan has a dynamic range of 1e12', () => {
- // This is the equivalent of zooming in to the nanosecond level, 1000 seconds
- // into a trace Note: this is about the limit of what this generator can
- // handle.
- let tickGen: TickGenerator|undefined = undefined;
- beforeAll(() => {
- const timeSpan = new TimeSpan(1000, 1000.000000001);
- const timeScale = new TimeScale(timeSpan, [0, 100]);
- tickGen = new TickGenerator(timeScale, {minLabelPx: 100});
+ it('throws an error when timespan duration is 0', () => {
+ expect(() => {
+ new TickGenerator(new TPTimeSpan(0n, 0n), 1);
+ }).toThrow(Error);
});
- it('should generate minor ticks at 1e-10s and one major tick at the start',
- () => {
- const expected = [
- {type: TickType.MAJOR, time: 1000.0000000000},
- {type: TickType.MINOR, time: 1000.0000000001},
- {type: TickType.MINOR, time: 1000.0000000002},
- {type: TickType.MINOR, time: 1000.0000000003},
- {type: TickType.MINOR, time: 1000.0000000004},
- {type: TickType.MEDIUM, time: 1000.0000000005},
- {type: TickType.MINOR, time: 1000.0000000006},
- {type: TickType.MINOR, time: 1000.0000000007},
- {type: TickType.MINOR, time: 1000.0000000008},
- {type: TickType.MINOR, time: 1000.0000000009},
- ];
- const actual = Array.from(tickGen!);
- expectTicksEqual(actual, expected);
- });
- it('should tell us to use 9 decimal places for labels', () => {
- expect(tickGen!.digits).toEqual(9);
+
+ it('throws an error when max ticks is 0', () => {
+ expect(() => {
+ new TickGenerator(new TPTimeSpan(0n, 1n), 0);
+ }).toThrow(Error);
});
});
-
-describe(
- 'TickGenerator where the timespan has a ridiculously huge dynamic range',
- () => {
- // We don't expect this to work, just wanna make sure it doesn't crash or
- // get stuck
- it('should not crash or get stuck in an infinite loop', () => {
- const timeSpan = new TimeSpan(1000, 1000.000000000001);
- const timeScale = new TimeScale(timeSpan, [0, 100]);
- new TickGenerator(timeScale);
- });
- });
-
-describe(
- 'TickGenerator where the timespan has a ridiculously huge dynamic range',
- () => {
- // We don't expect this to work, just wanna make sure it doesn't crash or
- // get stuck
- it('should not crash or get stuck in an infinite loop', () => {
- const timeSpan = new TimeSpan(1000, 1000.000000000001);
- const timeScale = new TimeScale(timeSpan, [0, 100]);
- new TickGenerator(timeScale);
- });
- });
-
-test('TickGenerator constructed with a 0 width throws an error', () => {
- expect(() => {
- const timeScale = new TimeScale(new TimeSpan(0.0, 1.0), [0, 0]);
- new TickGenerator(timeScale);
- }).toThrow(Error);
-});
-
-test(
- 'TickGenerator constructed with desiredPxPerStep of 0 throws an error',
- () => {
- expect(() => {
- new TickGenerator(timeScale, {minLabelPx: 0});
- }).toThrow(Error);
- });
-
-test('TickGenerator constructed with a 0 duration throws an error', () => {
- expect(() => {
- const timeScale = new TimeScale(new TimeSpan(0.0, 0.0), [0, 1]);
- new TickGenerator(timeScale);
- }).toThrow(Error);
-});
-
-function expectTicksEqual(actual: Tick[], expected: any[]) {
- // TODO(stevegolton) We could write a custom matcher for this; this approach
- // produces cryptic error messages.
- expect(actual.length).toEqual(expected.length);
- for (let i = 0; i < actual.length; ++i) {
- const ex = expected[i];
- const ac = actual[i];
- expect(ac.type).toEqual(ex.type);
- expect(ac.time).toBeCloseTo(ex.time, 9);
- }
-}
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index 7da04de..f25bf52 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -14,6 +14,7 @@
import {Actions} from '../common/actions';
import {Area} from '../common/state';
+import {TPTime} from '../common/time';
import {Flow, globals} from './globals';
import {toggleHelp} from './help_modal';
@@ -23,7 +24,8 @@
} from './scroll_helper';
import {executeSearch} from './search_handler';
-const INSTANT_FOCUS_DURATION_S = 1 / 1e9; // 1 ns.
+const INSTANT_FOCUS_DURATION = 1n;
+const INCOMPLETE_SLICE_DURATION = 30_000n;
type Direction = 'Forward'|'Backward';
// Handles all key events than are not handled by the
@@ -55,8 +57,8 @@
if (selection !== null && selection.kind === 'AREA') {
const area = globals.state.areas[selection.areaId];
const coversEntireTimeRange =
- globals.state.traceTime.startSec === area.startSec &&
- globals.state.traceTime.endSec === area.endSec;
+ globals.state.traceTime.start === area.start &&
+ globals.state.traceTime.end === area.end;
if (!coversEntireTimeRange) {
// If the current selection is an area which does not cover the entire
// time range, preserve the list of selected tracks and expand the time
@@ -71,10 +73,11 @@
// If the current selection is not an area, select all.
tracksToSelect = Object.keys(globals.state.tracks);
}
+ const {start, end} = globals.state.traceTime;
globals.dispatch(Actions.selectArea({
area: {
- startSec: globals.state.traceTime.startSec,
- endSec: globals.state.traceTime.endSec,
+ start,
+ end,
tracks: tracksToSelect,
},
}));
@@ -201,29 +204,29 @@
}
}
-function findTimeRangeOfSelection(): {startTs: number, endTs: number} {
+function findTimeRangeOfSelection(): {startTs: TPTime, endTs: TPTime} {
const selection = globals.state.currentSelection;
- let startTs = -1;
- let endTs = -1;
+ let startTs = -1n;
+ let endTs = -1n;
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;
+ startTs = slice.ts;
endTs = startTs + slice.dur;
} else if (slice.ts) {
- startTs = slice.ts + globals.state.traceTime.startSec;
+ startTs = slice.ts;
// This will handle either:
// a)slice.dur === -1 -> unfinished slice
// b)slice.dur === 0 -> instant event
- endTs = slice.dur === -1 ? globals.state.traceTime.endSec :
- startTs + INSTANT_FOCUS_DURATION_S;
+ endTs = slice.dur === -1n ? startTs + INCOMPLETE_SLICE_DURATION :
+ startTs + INSTANT_FOCUS_DURATION;
}
} else if (selection.kind === 'THREAD_STATE') {
const threadState = globals.threadStateDetails;
if (threadState.ts && threadState.dur) {
- startTs = threadState.ts + globals.state.traceTime.startSec;
+ startTs = threadState.ts;
endTs = startTs + threadState.dur;
}
} else if (selection.kind === 'COUNTER') {
@@ -232,8 +235,8 @@
} else if (selection.kind === 'AREA') {
const selectedArea = globals.state.areas[selection.areaId];
if (selectedArea) {
- startTs = selectedArea.startSec;
- endTs = selectedArea.endSec;
+ startTs = selectedArea.start;
+ endTs = selectedArea.end;
}
} else if (selection.kind === 'NOTE') {
const selectedNote = globals.state.notes[selection.id];
@@ -241,16 +244,18 @@
// above in the AREA case.
if (selectedNote && selectedNote.noteType === 'DEFAULT') {
startTs = selectedNote.timestamp;
- endTs = selectedNote.timestamp + INSTANT_FOCUS_DURATION_S;
+ endTs = selectedNote.timestamp + INSTANT_FOCUS_DURATION;
}
} else if (selection.kind === 'LOG') {
// TODO(hjd): Make focus selection work for logs.
- } else if (selection.kind === 'DEBUG_SLICE') {
- startTs = selection.startS;
- if (selection.durationS > 0) {
- endTs = startTs + selection.durationS;
+ } else if (
+ selection.kind === 'DEBUG_SLICE' ||
+ selection.kind === 'TOP_LEVEL_SCROLL') {
+ startTs = selection.start;
+ if (selection.duration > 0) {
+ endTs = startTs + selection.duration;
} else {
- endTs = startTs + INSTANT_FOCUS_DURATION_S;
+ endTs = startTs + INSTANT_FOCUS_DURATION;
}
}
@@ -260,12 +265,12 @@
function lockSliceSpan(persistent = false) {
const range = findTimeRangeOfSelection();
- if (range.startTs !== -1 && range.endTs !== -1 &&
+ if (range.startTs !== -1n && range.endTs !== -1n &&
globals.state.currentSelection !== null) {
const tracks = globals.state.currentSelection.trackId ?
[globals.state.currentSelection.trackId] :
[];
- const area: Area = {startSec: range.startTs, endSec: range.endTs, tracks};
+ const area: Area = {start: range.startTs, end: range.endTs, tracks};
globals.dispatch(Actions.markArea({area, persistent}));
}
}
@@ -275,7 +280,7 @@
if (selection === null) return;
const range = findTimeRangeOfSelection();
- if (range.startTs !== -1 && range.endTs !== -1) {
+ if (range.startTs !== -1n && range.endTs !== -1n) {
focusHorizontalRange(range.startTs, range.endTs);
}
diff --git a/ui/src/frontend/logs_panel.ts b/ui/src/frontend/logs_panel.ts
index 18ed325..88baa1c 100644
--- a/ui/src/frontend/logs_panel.ts
+++ b/ui/src/frontend/logs_panel.ts
@@ -16,14 +16,14 @@
import {assertExists} from '../base/logging';
import {Actions} from '../common/actions';
+import {HighPrecisionTimeSpan} from '../common/high_precision_time';
import {
LogBounds,
LogBoundsKey,
LogEntries,
LogEntriesKey,
} from '../common/logs';
-import {formatTimestamp} from '../common/time';
-import {TimeSpan} from '../common/time';
+import {formatTPTime, TPTime} from '../common/time';
import {SELECTED_LOG_ROWS_COLOR} from './css_constants';
import {globals} from './globals';
@@ -62,12 +62,16 @@
dom.parentElement!.parentElement!.parentElement as HTMLElement);
this.scrollContainer.addEventListener(
'scroll', this.onScroll.bind(this), {passive: true});
+ // TODO(stevegolton): Type assersions are a source of bugs.
+ // Let's try to find another way of doing this.
this.bounds = globals.trackDataStore.get(LogBoundsKey) as LogBounds;
this.entries = globals.trackDataStore.get(LogEntriesKey) as LogEntries;
this.recomputeVisibleRowsAndUpdate();
}
onbeforeupdate(_: m.CVnodeDOM) {
+ // TODO(stevegolton): Type assersions are a source of bugs.
+ // Let's try to find another way of doing this.
this.bounds = globals.trackDataStore.get(LogBoundsKey) as LogBounds;
this.entries = globals.trackDataStore.get(LogEntriesKey) as LogEntries;
this.recomputeVisibleRowsAndUpdate();
@@ -79,12 +83,12 @@
globals.rafScheduler.scheduleFullRedraw();
}
- onRowOver(ts: number) {
+ onRowOver(ts: TPTime) {
globals.dispatch(Actions.setHoverCursorTimestamp({ts}));
}
onRowOut() {
- globals.dispatch(Actions.setHoverCursorTimestamp({ts: -1}));
+ globals.dispatch(Actions.setHoverCursorTimestamp({ts: -1n}));
}
private totalRows():
@@ -92,17 +96,19 @@
if (!this.bounds) {
return {isStale: false, total: 0, offset: 0, count: 0};
}
- const {total, startTs, endTs, firstRowTs, lastRowTs} = this.bounds;
+ const {
+ totalVisibleLogs,
+ firstVisibleLogTs,
+ lastVisibleLogTs,
+ } = this.bounds;
const vis = globals.frontendLocalState.visibleWindowTime;
- const leftSpan = new TimeSpan(startTs, firstRowTs);
- const rightSpan = new TimeSpan(lastRowTs, endTs);
- const isStaleLeft = !leftSpan.isInBounds(vis.start);
- const isStaleRight = !rightSpan.isInBounds(vis.end);
- const isStale = isStaleLeft || isStaleRight;
- const offset = Math.min(this.visibleRowOffset, total);
- const visCount = Math.min(total - offset, this.visibleRowCount);
- return {isStale, total, count: visCount, offset};
+ const visibleLogSpan =
+ new HighPrecisionTimeSpan(firstVisibleLogTs, lastVisibleLogTs);
+ const isStale = !vis.contains(visibleLogSpan);
+ const offset = Math.min(this.visibleRowOffset, totalVisibleLogs);
+ const visCount = Math.min(totalVisibleLogs - offset, this.visibleRowCount);
+ return {isStale, total: totalVisibleLogs, count: visCount, offset};
}
view(_: m.CVnode<{}>) {
@@ -146,11 +152,10 @@
{
'class': isStale ? 'stale' : '',
style,
- 'onmouseover': this.onRowOver.bind(this, ts / 1e9),
+ 'onmouseover': this.onRowOver.bind(this, ts),
'onmouseout': this.onRowOut.bind(this),
},
- m('.cell',
- formatTimestamp(ts / 1e9 - globals.state.traceTime.startSec)),
+ m('.cell', formatTPTime(ts - globals.state.traceTime.start)),
m('.cell', priorityLetter || '?'),
m('.cell', tags[i]),
hasProcessNames ? m('.cell.with-process', processNames[i]) :
diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts
index d3eec07..27d9ec8 100644
--- a/ui/src/frontend/notes_panel.ts
+++ b/ui/src/frontend/notes_panel.ts
@@ -17,7 +17,9 @@
import {Actions} from '../common/actions';
import {randomColor} from '../common/colorizer';
import {AreaNote, Note} from '../common/state';
-import {timeToString} from '../common/time';
+import {
+ tpTimeToString,
+} from '../common/time';
import {
BottomTab,
@@ -28,6 +30,7 @@
import {PerfettoMouseEvent} from './events';
import {globals} from './globals';
import {
+ getMaxMajorTicks,
TickGenerator,
TickType,
timeScaleForVisibleWindow,
@@ -46,7 +49,7 @@
function getStartTimestamp(note: Note|AreaNote) {
if (note.noteType === 'AREA') {
- return globals.state.areas[note.areaId].startSec;
+ return globals.state.areas[note.areaId].start;
} else {
return note.timestamp;
}
@@ -66,7 +69,7 @@
});
dom.addEventListener('mouseout', () => {
this.hoveredX = null;
- globals.dispatch(Actions.setHoveredNoteTimestamp({ts: -1}));
+ globals.dispatch(Actions.setHoveredNoteTimestamp({ts: -1n}));
}, {passive: true});
}
@@ -110,15 +113,27 @@
}
renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
- const timeScale = globals.frontendLocalState.timeScale;
let aNoteIsHovered = false;
ctx.fillStyle = '#999';
ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
- const relScale = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
- if (relScale.timeSpan.duration > 0 && relScale.widthPx > 0) {
- for (const {type, position} of new TickGenerator(relScale)) {
- if (type === TickType.MAJOR) ctx.fillRect(position, 0, 1, size.height);
+
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height);
+ ctx.clip();
+
+ const span = globals.frontendLocalState.visibleWindow.timestampSpan;
+ const {visibleTimeScale} = globals.frontendLocalState;
+ if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) {
+ const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH);
+ const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
+ for (const {type, time} of new TickGenerator(
+ span, maxMajorTicks, globals.state.traceTime.start)) {
+ const px = Math.floor(map.tpTimeToPx(time));
+ if (type === TickType.MAJOR) {
+ ctx.fillRect(px, 0, 1, size.height);
+ }
}
}
@@ -129,11 +144,10 @@
const timestamp = getStartTimestamp(note);
// TODO(hjd): We should still render area selection marks in viewport is
// *within* the area (e.g. both lhs and rhs are out of bounds).
- if ((note.noteType !== 'AREA' && !timeScale.timeInBounds(timestamp)) ||
+ if ((note.noteType !== 'AREA' && !span.contains(timestamp)) ||
(note.noteType === 'AREA' &&
- !timeScale.timeInBounds(globals.state.areas[note.areaId].endSec) &&
- !timeScale.timeInBounds(
- globals.state.areas[note.areaId].startSec))) {
+ !span.contains(globals.state.areas[note.areaId].end) &&
+ !span.contains(globals.state.areas[note.areaId].start))) {
continue;
}
const currentIsHovered =
@@ -144,7 +158,7 @@
const isSelected = selection !== null &&
((selection.kind === 'NOTE' && selection.id === note.id) ||
(selection.kind === 'AREA' && selection.noteId === note.id));
- const x = timeScale.timeToPx(timestamp);
+ const x = visibleTimeScale.tpTimeToPx(timestamp);
const left = Math.floor(x + TRACK_SHELL_WIDTH);
// Draw flag or marker.
@@ -153,7 +167,8 @@
this.drawAreaMarker(
ctx,
left,
- Math.floor(timeScale.timeToPx(area.endSec) + TRACK_SHELL_WIDTH),
+ Math.floor(
+ visibleTimeScale.tpTimeToPx(area.end) + TRACK_SHELL_WIDTH),
note.color,
isSelected);
} else {
@@ -175,19 +190,21 @@
// 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.dispatch(Actions.setHoveredNoteTimestamp({ts: -1}));
+ globals.dispatch(Actions.setHoveredNoteTimestamp({ts: -1n}));
}
// View preview note flag when hovering on notes panel.
if (!aNoteIsHovered && this.hoveredX !== null) {
- const timestamp = timeScale.pxToTime(this.hoveredX);
- if (timeScale.timeInBounds(timestamp)) {
+ const timestamp = visibleTimeScale.pxToHpTime(this.hoveredX).toTPTime();
+ if (span.contains(timestamp)) {
globals.dispatch(Actions.setHoveredNoteTimestamp({ts: timestamp}));
- const x = timeScale.timeToPx(timestamp);
+ const x = visibleTimeScale.tpTimeToPx(timestamp);
const left = Math.floor(x + TRACK_SHELL_WIDTH);
this.drawFlag(ctx, left, size.height, '#aaa', /* fill */ true);
}
}
+
+ ctx.restore();
}
private drawAreaMarker(
@@ -197,7 +214,7 @@
ctx.strokeStyle = color;
const topOffset = 10;
// Don't draw in the track shell section.
- if (x >= globals.frontendLocalState.timeScale.startPx + TRACK_SHELL_WIDTH) {
+ if (x >= globals.frontendLocalState.windowSpan.start + TRACK_SHELL_WIDTH) {
// Draw left triangle.
ctx.beginPath();
ctx.moveTo(x, topOffset);
@@ -218,7 +235,7 @@
// Start line after track shell section, join triangles.
const startDraw = Math.max(
- x, globals.frontendLocalState.timeScale.startPx + TRACK_SHELL_WIDTH);
+ x, globals.frontendLocalState.windowSpan.start + TRACK_SHELL_WIDTH);
ctx.beginPath();
ctx.moveTo(startDraw, topOffset);
ctx.lineTo(xEnd, topOffset);
@@ -250,8 +267,8 @@
private onClick(x: number, _: number) {
if (x < 0) return;
- const timeScale = globals.frontendLocalState.timeScale;
- const timestamp = timeScale.pxToTime(x);
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const timestamp = visibleTimeScale.pxToHpTime(x).toTPTime();
for (const note of Object.values(globals.state.notes)) {
if (this.hoveredX && this.mouseOverNote(this.hoveredX, note)) {
if (note.noteType === 'AREA') {
@@ -268,13 +285,13 @@
}
private mouseOverNote(x: number, note: AreaNote|Note): boolean {
- const timeScale = globals.frontendLocalState.timeScale;
- const noteX = timeScale.timeToPx(getStartTimestamp(note));
+ const timeScale = globals.frontendLocalState.visibleTimeScale;
+ const noteX = timeScale.tpTimeToPx(getStartTimestamp(note));
if (note.noteType === 'AREA') {
const noteArea = globals.state.areas[note.areaId];
return (noteX <= x && x < noteX + AREA_TRIANGLE_WIDTH) ||
- (timeScale.timeToPx(noteArea.endSec) > x &&
- x > timeScale.timeToPx(noteArea.endSec) - AREA_TRIANGLE_WIDTH);
+ (timeScale.tpTimeToPx(noteArea.end) > x &&
+ x > timeScale.tpTimeToPx(noteArea.end) - AREA_TRIANGLE_WIDTH);
} else {
const width = FLAG_WIDTH;
return noteX <= x && x < noteX + width;
@@ -308,13 +325,12 @@
if (note === undefined) {
return m('.', `No Note with id ${this.config.id}`);
}
- const startTime =
- getStartTimestamp(note) - globals.state.traceTime.startSec;
+ const startTime = getStartTimestamp(note) - globals.state.traceTime.start;
return m(
'.notes-editor-panel',
m('.notes-editor-panel-heading-bar',
m('.notes-editor-panel-heading',
- `Annotation at ${timeToString(startTime)}`),
+ `Annotation at ${tpTimeToString(startTime)}`),
m('input[type=text]', {
onkeydown: (e: Event) => {
e.stopImmediatePropagation();
diff --git a/ui/src/frontend/overview_timeline_panel.ts b/ui/src/frontend/overview_timeline_panel.ts
index 76b4515..54f932e 100644
--- a/ui/src/frontend/overview_timeline_panel.ts
+++ b/ui/src/frontend/overview_timeline_panel.ts
@@ -14,9 +14,12 @@
import m from 'mithril';
-import {assertExists} from '../base/logging';
import {hueForCpu} from '../common/colorizer';
-import {TimeSpan} from '../common/time';
+import {
+ Span,
+ TPTime,
+ tpTimeToSeconds,
+} from '../common/time';
import {
OVERVIEW_TIMELINE_NON_VISIBLE_COLOR,
@@ -29,9 +32,9 @@
import {OuterDragStrategy} from './drag/outer_drag_strategy';
import {DragGestureHandler} from './drag_gesture_handler';
import {globals} from './globals';
-import {TickGenerator, TickType} from './gridline_helper';
+import {getMaxMajorTicks, TickGenerator, TickType} from './gridline_helper';
import {Panel, PanelSize} from './panel';
-import {TimeScale} from './time_scale';
+import {PxSpan, TimeScale} from './time_scale';
export class OverviewTimelinePanel extends Panel {
private static HANDLE_SIZE_PX = 5;
@@ -39,7 +42,7 @@
private width = 0;
private gesture?: DragGestureHandler;
private timeScale?: TimeScale;
- private totTime = new TimeSpan(0, 0);
+ private traceTime?: Span<TPTime>;
private dragStrategy?: DragStrategy;
private readonly boundOnMouseMove = this.onMouseMove.bind(this);
@@ -47,11 +50,11 @@
// https://github.com/Microsoft/TypeScript/issues/1373
onupdate({dom}: m.CVnodeDOM) {
this.width = dom.getBoundingClientRect().width;
- this.totTime = new TimeSpan(
- globals.state.traceTime.startSec, globals.state.traceTime.endSec);
- this.timeScale = new TimeScale(
- this.totTime, [TRACK_SHELL_WIDTH, assertExists(this.width)]);
-
+ this.traceTime = globals.stateTraceTimeTP();
+ const traceTime = globals.stateTraceTime();
+ const pxSpan = new PxSpan(TRACK_SHELL_WIDTH, this.width);
+ this.timeScale =
+ new TimeScale(traceTime.start, traceTime.duration.nanos, pxSpan);
if (this.gesture === undefined) {
this.gesture = new DragGestureHandler(
dom as HTMLElement,
@@ -78,26 +81,27 @@
renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
if (this.width === undefined) return;
+ if (this.traceTime === undefined) return;
if (this.timeScale === undefined) return;
const headerHeight = 20;
const tracksHeight = size.height - headerHeight;
- const timeSpan = new TimeSpan(0, this.totTime.duration);
- const timeScale = new TimeScale(timeSpan, [TRACK_SHELL_WIDTH, this.width]);
-
- if (timeScale.timeSpan.duration > 0 && timeScale.widthPx > 0) {
- const tickGen = new TickGenerator(timeScale);
+ if (size.width > TRACK_SHELL_WIDTH && this.traceTime.duration > 0n) {
+ const maxMajorTicks = getMaxMajorTicks(this.width - TRACK_SHELL_WIDTH);
+ const tickGen = new TickGenerator(
+ this.traceTime, maxMajorTicks, globals.state.traceTime.start);
// Draw time labels on the top header.
ctx.font = '10px Roboto Condensed';
ctx.fillStyle = '#999';
- for (const {type, time, position} of tickGen) {
- const xPos = Math.round(position);
+ for (const {type, time} of tickGen) {
+ const xPos = Math.floor(this.timeScale.tpTimeToPx(time));
if (xPos <= 0) continue;
if (xPos > this.width) break;
if (type === TickType.MAJOR) {
ctx.fillRect(xPos - 1, 0, 1, headerHeight - 5);
- ctx.fillText(time.toFixed(tickGen.digits) + ' s', xPos + 5, 18);
+ const sec = tpTimeToSeconds(time - globals.state.traceTime.start);
+ ctx.fillText(sec.toFixed(tickGen.digits) + ' s', xPos + 5, 18);
} else if (type == TickType.MEDIUM) {
ctx.fillRect(xPos - 1, 0, 1, 8);
} else if (type == TickType.MINOR) {
@@ -114,8 +118,8 @@
for (const key of globals.overviewStore.keys()) {
const loads = globals.overviewStore.get(key)!;
for (let i = 0; i < loads.length; i++) {
- const xStart = Math.floor(this.timeScale.timeToPx(loads[i].startSec));
- const xEnd = Math.ceil(this.timeScale.timeToPx(loads[i].endSec));
+ const xStart = Math.floor(this.timeScale.tpTimeToPx(loads[i].start));
+ const xEnd = Math.ceil(this.timeScale.tpTimeToPx(loads[i].end));
const yOff = Math.floor(headerHeight + y * trackHeight);
const lightness = Math.ceil((1 - loads[i].load * 0.7) * 100);
ctx.fillStyle = `hsl(${hueForCpu(y)}, 50%, ${lightness}%)`;
@@ -210,10 +214,10 @@
}
private static extractBounds(timeScale: TimeScale): [number, number] {
- const vizTime = globals.frontendLocalState.getVisibleStateBounds();
+ const vizTime = globals.frontendLocalState.visibleWindowTime;
return [
- Math.floor(timeScale.timeToPx(vizTime[0])),
- Math.ceil(timeScale.timeToPx(vizTime[1])),
+ Math.floor(timeScale.hpTimeToPx(vizTime.start)),
+ Math.ceil(timeScale.hpTimeToPx(vizTime.end)),
];
}
diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts
index 4c6576f..b7841d7 100644
--- a/ui/src/frontend/panel_container.ts
+++ b/ui/src/frontend/panel_container.ts
@@ -135,11 +135,13 @@
return;
}
+ const {visibleTimeScale} = globals.frontendLocalState;
+
// The Y value is given from the top of the pan and zoom region, we want it
// from the top of the panel container. The parent offset corrects that.
const panels = this.getPanelsInRegion(
- globals.frontendLocalState.timeScale.timeToPx(area.startSec),
- globals.frontendLocalState.timeScale.timeToPx(area.endSec),
+ visibleTimeScale.tpTimeToPx(area.start),
+ visibleTimeScale.tpTimeToPx(area.end),
globals.frontendLocalState.areaY.start + TOPBAR_HEIGHT,
globals.frontendLocalState.areaY.end + TOPBAR_HEIGHT);
// Get the track ids from the panels.
@@ -160,7 +162,7 @@
}
}
}
- globals.frontendLocalState.selectArea(area.startSec, area.endSec, tracks);
+ globals.frontendLocalState.selectArea(area.start, area.end, tracks);
}
constructor(vnode: m.CVnode<Attrs>) {
@@ -449,8 +451,9 @@
return;
}
- const startX = globals.frontendLocalState.timeScale.timeToPx(area.startSec);
- const endX = globals.frontendLocalState.timeScale.timeToPx(area.endSec);
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const startX = visibleTimeScale.tpTimeToPx(area.start);
+ const endX = visibleTimeScale.tpTimeToPx(area.end);
// To align with where to draw on the canvas subtract the first panel Y.
selectedTracksMinY -= this.panelContainerTop;
selectedTracksMaxY -= this.panelContainerTop;
diff --git a/ui/src/frontend/pivot_table_query_generator.ts b/ui/src/frontend/pivot_table_query_generator.ts
index 0c61f56..dffa6e4 100644
--- a/ui/src/frontend/pivot_table_query_generator.ts
+++ b/ui/src/frontend/pivot_table_query_generator.ts
@@ -20,7 +20,6 @@
PivotTableQuery,
PivotTableState,
} from '../common/state';
-import {toNs} from '../common/time';
import {
getSelectedTrackIds,
} from '../controller/aggregation/slice_aggregation_controller';
@@ -100,8 +99,8 @@
export function areaFilter(area: Area): string {
return `
- ts + dur > ${toNs(area.startSec)}
- and ts < ${toNs(area.endSec)}
+ ts + dur > ${area.start}
+ and ts < ${area.end}
and track_id in (${getSelectedTrackIds(area).join(', ')})
`;
}
diff --git a/ui/src/frontend/publish.ts b/ui/src/frontend/publish.ts
index 7632e53..0cc5604 100644
--- a/ui/src/frontend/publish.ts
+++ b/ui/src/frontend/publish.ts
@@ -54,6 +54,11 @@
globals.rafScheduler.scheduleRedraw();
}
+export function clearOverviewData() {
+ globals.overviewStore.clear();
+ globals.rafScheduler.scheduleRedraw();
+}
+
export function publishTrackData(args: {id: string, data: {}}) {
globals.setTrackData(args.id, args.data);
if ([LogExistsKey, LogBoundsKey, LogEntriesKey].includes(args.id)) {
diff --git a/ui/src/frontend/query_table.ts b/ui/src/frontend/query_table.ts
index c27ecc2..a77c0ef 100644
--- a/ui/src/frontend/query_table.ts
+++ b/ui/src/frontend/query_table.ts
@@ -14,22 +14,19 @@
import m from 'mithril';
+import {BigintMath} from '../base/bigint_math';
import {Actions} from '../common/actions';
import {QueryResponse} from '../common/queries';
-import {ColumnType, Row} from '../common/query_result';
-import {fromNs} from '../common/time';
-import {Anchor} from './anchor';
+import {Row} from '../common/query_result';
+import {Anchor} from './anchor';
import {copyToClipboard, queryResponseToClipboard} from './clipboard';
import {downloadData} from './download_utils';
import {globals} from './globals';
import {Panel} from './panel';
import {Router} from './router';
-import {
- focusHorizontalRange,
- verticalScrollToTrack,
-} from './scroll_helper';
+import {reveal} from './scroll_helper';
import {Button} from './widgets/button';
interface QueryTableRowAttrs {
@@ -37,98 +34,126 @@
columns: string[];
}
-// Convert column value to number if it's a bigint or a number, otherwise throw
-function colToNumber(colValue: ColumnType): number {
- if (typeof colValue === 'bigint') {
- return Number(colValue);
- } else if (typeof colValue === 'number') {
- return colValue;
+type Numeric = bigint|number;
+
+function isIntegral(x: Row[string]): x is Numeric {
+ return typeof x === 'bigint' ||
+ (typeof x === 'number' && Number.isInteger(x));
+}
+
+function hasTs(row: Row): row is Row&{ts: Numeric} {
+ return ('ts' in row && isIntegral(row.ts));
+}
+
+function hasDur(row: Row): row is Row&{dur: Numeric} {
+ return ('dur' in row && isIntegral(row.dur));
+}
+
+function hasTrackId(row: Row): row is Row&{track_id: Numeric} {
+ return ('track_id' in row && isIntegral(row.track_id));
+}
+
+function hasType(row: Row): row is Row&{type: string} {
+ return ('type' in row && typeof row.type === 'string');
+}
+
+function hasId(row: Row): row is Row&{id: Numeric} {
+ return ('id' in row && isIntegral(row.id));
+}
+
+function hasSliceId(row: Row): row is Row&{slice_id: Numeric} {
+ return ('slice_id' in row && isIntegral(row.slice_id));
+}
+
+// These are properties that a row should have in order to be "slice-like",
+// insofar as it represents a time range and a track id which can be revealed
+// or zoomed-into on the timeline.
+type Sliceish = {
+ ts: Numeric,
+ dur: Numeric,
+ track_id: Numeric
+};
+
+export function isSliceish(row: Row): row is Row&Sliceish {
+ return hasTs(row) && hasDur(row) && hasTrackId(row);
+}
+
+// Attempts to extract a slice ID from a row, or undefined if none can be found
+export function getSliceId(row: Row): number|undefined {
+ if (hasType(row) && row.type.includes('slice')) {
+ if (hasId(row)) {
+ return Number(row.id);
+ }
} else {
- throw Error('Value is not a number or a bigint');
+ if (hasSliceId(row)) {
+ return Number(row.slice_id);
+ }
}
+ return undefined;
}
class QueryTableRow implements m.ClassComponent<QueryTableRowAttrs> {
- static columnsContainsSliceLocation(columns: string[]) {
- const requiredColumns = ['ts', 'dur', 'track_id'];
- for (const col of requiredColumns) {
- if (!columns.includes(col)) return false;
- }
- return true;
- }
-
- static rowOnClickHandler(
- event: Event, row: Row, nextTab: 'CurrentSelection'|'QueryResults') {
- // TODO(dproy): Make click handler work from analyze page.
- 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();
-
- const sliceStart = fromNs(colToNumber(row.ts));
- // row.dur can be negative. Clamp to 1ns.
- const sliceDur = fromNs(Math.max(colToNumber(row.dur), 1));
- const sliceEnd = sliceStart + sliceDur;
- const trackId: number = colToNumber(row.track_id);
- const uiTrackId = globals.state.uiTrackIdByTraceTrackId[trackId];
- if (uiTrackId === undefined) return;
- verticalScrollToTrack(uiTrackId, true);
- // TODO(stevegolton) Soon this function will only accept Bigints
- focusHorizontalRange(sliceStart, sliceEnd);
-
- let sliceId: number|undefined;
- if (row.type?.toString().includes('slice')) {
- sliceId = colToNumber(row.id);
- } else {
- sliceId = colToNumber(row.slice_id);
- }
- if (sliceId !== undefined) {
- globals.makeSelection(
- Actions.selectChromeSlice(
- {id: sliceId, trackId: uiTrackId, table: 'slice'}),
- nextTab === 'QueryResults' ? globals.state.currentTab :
- 'current_selection');
- }
- }
-
view(vnode: m.Vnode<QueryTableRowAttrs>) {
- const cells = [];
const {row, columns} = vnode.attrs;
- for (const col of columns) {
- const value = row[col];
- if (value instanceof Uint8Array) {
- cells.push(
- m('td',
- m(Anchor,
- {
- onclick: () => downloadData(`${col}.blob`, value),
- },
- `Blob (${value.length} bytes)`)));
- } else if (typeof value === 'bigint') {
- cells.push(m('td', value.toString()));
- } else {
- cells.push(m('td', value));
+ const cells = columns.map((col) => this.renderCell(col, row[col]));
+
+ // TODO(dproy): Make click handler work from analyze page.
+ if (Router.parseUrl(window.location.href).page === '/viewer' &&
+ isSliceish(row)) {
+ return m(
+ 'tr',
+ {
+ onclick: () => this.highlightSlice(row, globals.state.currentTab),
+ // TODO(altimin): Consider improving the logic here (e.g. delay?) to
+ // account for cases when dblclick fires late.
+ ondblclick: () => this.highlightSlice(row),
+ clickable: true,
+ },
+ cells);
+ } else {
+ return m('tr', cells);
+ }
+ }
+
+ private renderCell(name: string, value: Row[string]) {
+ if (value instanceof Uint8Array) {
+ return m('td', this.renderBlob(name, value));
+ } else {
+ return m('td', `${value}`);
+ }
+ }
+
+ private renderBlob(name: string, value: Uint8Array) {
+ return m(
+ Anchor,
+ {
+ onclick: () => downloadData(`${name}.blob`, value),
+ },
+ `Blob (${value.length} bytes)`);
+ }
+
+ private highlightSlice(row: Row&Sliceish, nextTab?: string) {
+ const trackId = Number(row.track_id);
+ const sliceStart = BigInt(row.ts);
+ // row.dur can be negative. Clamp to 1ns.
+ const sliceDur = BigintMath.max(BigInt(row.dur), 1n);
+ const uiTrackId = globals.state.uiTrackIdByTraceTrackId[trackId];
+ if (uiTrackId !== undefined) {
+ reveal(uiTrackId, sliceStart, sliceStart + sliceDur, true);
+ const sliceId = getSliceId(row);
+ if (sliceId !== undefined) {
+ this.selectSlice(sliceId, uiTrackId, nextTab);
}
}
- const containsSliceLocation =
- QueryTableRow.columnsContainsSliceLocation(columns);
- const maybeOnClick = containsSliceLocation ?
- (e: Event) => QueryTableRow.rowOnClickHandler(e, row, 'QueryResults') :
- null;
- const maybeOnDblClick = containsSliceLocation ?
- (e: Event) =>
- QueryTableRow.rowOnClickHandler(e, row, 'CurrentSelection') :
- null;
- return m(
- 'tr',
- {
- 'onclick': maybeOnClick,
- // TODO(altimin): Consider improving the logic here (e.g. delay?) to
- // account for cases when dblclick fires late.
- 'ondblclick': maybeOnDblClick,
- 'clickable': containsSliceLocation,
- },
- cells);
+ }
+
+ private selectSlice(sliceId: number, uiTrackId: string, nextTab?: string) {
+ const action = Actions.selectChromeSlice({
+ id: sliceId,
+ trackId: uiTrackId,
+ table: 'slice',
+ });
+ globals.makeSelection(action, nextTab);
}
}
diff --git a/ui/src/frontend/query_table_unittest.ts b/ui/src/frontend/query_table_unittest.ts
new file mode 100644
index 0000000..fc351a6
--- /dev/null
+++ b/ui/src/frontend/query_table_unittest.ts
@@ -0,0 +1,46 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {getSliceId, isSliceish} from './query_table';
+
+describe('getSliceId', () => {
+ test('get slice_id if present when no other clues are available', () => {
+ expect(getSliceId({})).toBe(undefined);
+ expect(getSliceId({id: 123})).toBe(undefined);
+ expect(getSliceId({slice_id: 456})).toBe(456);
+ expect(getSliceId({id: 123, slice_id: 456})).toBe(456);
+
+ expect(getSliceId({type: 'foo'})).toBe(undefined);
+ expect(getSliceId({type: 'foo', id: 123})).toBe(undefined);
+ expect(getSliceId({type: 'foo', slice_id: 456})).toBe(456);
+ expect(getSliceId({type: 'foo', id: 123, slice_id: 456})).toBe(456);
+ });
+
+ test('get id if present when row looks like a slice', () => {
+ expect(getSliceId({type: 'slice'})).toBe(undefined);
+ expect(getSliceId({type: 'slice', id: 123})).toBe(123);
+ expect(getSliceId({type: 'slice', slice_id: 456})).toBe(undefined);
+ expect(getSliceId({type: 'slice', id: 123, slice_id: 456})).toBe(123);
+ });
+});
+
+test('isSliceish', () => {
+ expect(isSliceish({})).toBeFalsy();
+ expect(isSliceish({ts: 123, dur: 456})).toBeFalsy();
+ expect(isSliceish({ts: 123, dur: 456, track_id: 798})).toBeTruthy();
+ expect(isSliceish({ts: 123n, dur: 456n})).toBeFalsy();
+ expect(isSliceish({ts: 123n, dur: 456n, track_id: 798n})).toBeTruthy();
+ expect(isSliceish({ts: 123.4, dur: 456.7, track_id: 798.9})).toBeFalsy();
+ expect(isSliceish({ts: '123', dur: '456', track_id: '789'})).toBeFalsy();
+});
diff --git a/ui/src/frontend/scroll_helper.ts b/ui/src/frontend/scroll_helper.ts
index 18a9a78..671fd4b 100644
--- a/ui/src/frontend/scroll_helper.ts
+++ b/ui/src/frontend/scroll_helper.ts
@@ -13,23 +13,28 @@
// limitations under the License.
import {Actions} from '../common/actions';
+import {
+ HighPrecisionTime,
+ HighPrecisionTimeSpan,
+} from '../common/high_precision_time';
import {getContainingTrackId} from '../common/state';
-import {fromNs, TimeSpan, toNs} from '../common/time';
+import {TPTime} from '../common/time';
import {globals} from './globals';
-const INCOMPLETE_SLICE_TIME_S = 0.00003;
// Given a timestamp, if |ts| is not currently in view move the view to
// center |ts|, keeping the same zoom level.
-export function horizontalScrollToTs(ts: number) {
- const startNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
- const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
- const currentViewNs = endNs - startNs;
- if (ts < startNs || ts > endNs) {
+// TODO(stevegolton): Remove me!
+export function horizontalScrollToTs(ts: TPTime) {
+ console.log('horizontalScrollToTs', ts);
+ const time = HighPrecisionTime.fromTPTime(ts);
+ const {start, end, duration} = globals.frontendLocalState.visibleWindowTime;
+ const halfDuration = duration.nanos / 2;
+ if (time.isLessThan(start) || time.isGreaterThan(end)) {
// TODO(hjd): This is an ugly jump, we should do a smooth pan instead.
- globals.frontendLocalState.updateVisibleTime(new TimeSpan(
- fromNs(ts - currentViewNs / 2), fromNs(ts + currentViewNs / 2)));
+ globals.frontendLocalState.updateVisibleTime(new HighPrecisionTimeSpan(
+ time.subtractNanos(halfDuration), time.addNanos(halfDuration)));
}
}
@@ -46,16 +51,11 @@
// to cover 1/5 of the viewport.
// - Otherwise, preserve the zoom range.
export function focusHorizontalRange(
- startTs: number, endTs: number, viewPercentage?: number) {
- const visibleDur = globals.frontendLocalState.visibleWindowTime.end -
- globals.frontendLocalState.visibleWindowTime.start;
- let selectDur = endTs - startTs;
- // TODO(altimin): We go from `ts` and `dur` to `startTs` and `endTs` and back
- // to `dur`. We should fix that.
- if (toNs(selectDur) === -1) { // Unfinished slice
- selectDur = INCOMPLETE_SLICE_TIME_S;
- endTs = startTs;
- }
+ start: TPTime, end: TPTime, viewPercentage?: number) {
+ console.log('focusHorizontalRange', start, end);
+ const visible = globals.frontendLocalState.visibleWindowTime;
+ const trace = globals.stateTraceTime();
+ const select = HighPrecisionTimeSpan.fromTpTime(start, end);
if (viewPercentage !== undefined) {
if (viewPercentage <= 0.0 || viewPercentage > 1.0) {
@@ -67,51 +67,43 @@
viewPercentage = 0.5;
}
const paddingPercentage = 1.0 - viewPercentage;
- const paddingTime = selectDur * paddingPercentage;
- const halfPaddingTime = paddingTime / 2;
- globals.frontendLocalState.updateVisibleTime(
- new TimeSpan(startTs - halfPaddingTime, endTs + halfPaddingTime));
+ const paddingTime = select.duration.multiply(paddingPercentage);
+ const halfPaddingTime = paddingTime.divide(2);
+ globals.frontendLocalState.updateVisibleTime(select.pad(halfPaddingTime));
return;
}
-
// If the range is too large to fit on the current zoom level, resize.
- if (selectDur > 0.5 * visibleDur) {
- globals.frontendLocalState.updateVisibleTime(
- new TimeSpan(startTs - (selectDur * 2), endTs + (selectDur * 2)));
+ if (select.duration.isGreaterThan(visible.duration.multiply(0.5))) {
+ const paddedRange = select.pad(select.duration.multiply(2));
+ globals.frontendLocalState.updateVisibleTime(paddedRange);
return;
}
- const midpointTs = (endTs + startTs) / 2;
// Calculate the new visible window preserving the zoom level.
- let newStartTs = midpointTs - visibleDur / 2;
- let newEndTs = midpointTs + visibleDur / 2;
+ let newStart = select.midpoint.subtract(visible.duration.divide(2));
+ let newEnd = select.midpoint.add(visible.duration.divide(2));
// Adjust the new visible window if it intersects with the trace boundaries.
// It's needed to make the "update the zoom level if visible window doesn't
// change" logic reliable.
- if (newEndTs > globals.state.traceTime.endSec) {
- newStartTs = globals.state.traceTime.endSec - visibleDur;
- newEndTs = globals.state.traceTime.endSec;
+ if (newEnd.isGreaterThan(trace.end)) {
+ newStart = trace.end.subtract(visible.duration);
+ newEnd = trace.end;
}
- if (newStartTs < globals.state.traceTime.startSec) {
- newStartTs = globals.state.traceTime.startSec;
- newEndTs = globals.state.traceTime.startSec + visibleDur;
+ if (newStart.isLessThan(trace.start)) {
+ newStart = trace.start;
+ newEnd = trace.start.add(visible.duration);
}
- const newStartNs = toNs(newStartTs);
- const newEndNs = toNs(newEndTs);
-
- const viewStartNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
- const viewEndNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
+ const view = new HighPrecisionTimeSpan(newStart, newEnd);
// If preserving the zoom doesn't change the visible window, update the zoom
// level.
- if (newStartNs === viewStartNs && newEndNs === viewEndNs) {
- globals.frontendLocalState.updateVisibleTime(
- new TimeSpan(startTs - (selectDur * 2), endTs + (selectDur * 2)));
- return;
+ if (view.start.equals(visible.start) && view.end.equals(visible.end)) {
+ const padded = select.pad(select.duration.multiply(2));
+ globals.frontendLocalState.updateVisibleTime(padded);
+ } else {
+ globals.frontendLocalState.updateVisibleTime(view);
}
- globals.frontendLocalState.updateVisibleTime(
- new TimeSpan(newStartTs, newEndTs));
}
// Given a track id, find a track with that id and scroll it into view. If the
@@ -155,9 +147,16 @@
// Scroll vertically and horizontally to reach track (|trackId|) at |ts|.
export function scrollToTrackAndTs(
- trackId: string|number|undefined, ts: number, openGroup = false) {
+ trackId: string|number|undefined, ts: TPTime, openGroup = false) {
if (trackId !== undefined) {
verticalScrollToTrack(trackId, openGroup);
}
horizontalScrollToTs(ts);
}
+
+// Scroll vertically and horizontally to a track and time range
+export function reveal(
+ trackId: string|number, start: TPTime, end: TPTime, openGroup = false) {
+ verticalScrollToTrack(trackId, openGroup);
+ focusHorizontalRange(start, end);
+}
diff --git a/ui/src/frontend/search_handler.ts b/ui/src/frontend/search_handler.ts
index 1622a7e..f995617 100644
--- a/ui/src/frontend/search_handler.ts
+++ b/ui/src/frontend/search_handler.ts
@@ -14,8 +14,6 @@
import {searchSegment} from '../base/binary_search';
import {Actions} from '../common/actions';
-import {toNs} from '../common/time';
-
import {globals} from './globals';
function setToPrevious(current: number) {
@@ -34,8 +32,9 @@
export function executeSearch(reverse = false) {
const index = globals.state.searchIndex;
- const startNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
- const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
+ const vizWindow = globals.frontendLocalState.visibleWindowTime;
+ const startNs = vizWindow.start.nanos;
+ const endNs = vizWindow.end.nanos;
const currentTs = globals.currentSearchResults.tsStarts[index];
// If the value of |globals.currentSearchResults.totalResults| is 0,
diff --git a/ui/src/frontend/slice.ts b/ui/src/frontend/slice.ts
index 5b660ef..7587a27 100644
--- a/ui/src/frontend/slice.ts
+++ b/ui/src/frontend/slice.ts
@@ -13,13 +13,14 @@
// limitations under the License.
import {Color} from '../common/colorizer';
+import {TPDuration, TPTime} from '../common/time';
export interface Slice {
// These properties are updated only once per query result when the Slice
// object is created and don't change afterwards.
readonly id: number;
- readonly startS: number;
- readonly durationS: number;
+ readonly start: TPTime;
+ readonly duration: TPDuration;
readonly depth: number;
readonly flags: number;
diff --git a/ui/src/frontend/slice_details_panel.ts b/ui/src/frontend/slice_details_panel.ts
index 9b018dd..13e3dd5 100644
--- a/ui/src/frontend/slice_details_panel.ts
+++ b/ui/src/frontend/slice_details_panel.ts
@@ -16,7 +16,7 @@
import {Actions} from '../common/actions';
import {translateState} from '../common/thread_state';
-import {timeToCode, toNs} from '../common/time';
+import {tpTimeToCode} from '../common/time';
import {globals, SliceDetails, ThreadDesc} from './globals';
import {scrollToTrackAndTs} from './scroll_helper';
import {SlicePanel} from './slice_panel';
@@ -60,9 +60,8 @@
if (!threadInfo) {
return null;
}
- const timestamp = timeToCode(
- sliceInfo.wakeupTs! - globals.state.traceTime.startSec,
- );
+ const timestamp =
+ tpTimeToCode(sliceInfo.wakeupTs! - globals.state.traceTime.start);
return m(
'.slice-details-wakeup-text',
m('', `Wakeup @ ${timestamp} on CPU ${sliceInfo.wakerCpu} by`),
@@ -76,9 +75,7 @@
return null;
}
- const latency = timeToCode(
- sliceInfo.ts - (sliceInfo.wakeupTs - globals.state.traceTime.startSec),
- );
+ const latency = tpTimeToCode(sliceInfo.ts - sliceInfo.wakeupTs);
return m(
'.slice-details-latency-text',
m('', `Scheduling latency: ${latency}`),
@@ -111,7 +108,10 @@
{onclick: () => this.goToThread(), title: 'Go to thread'},
'call_made'))),
m('tr', m('th', `Cmdline`), m('td', threadInfo.cmdline)),
- m('tr', m('th', `Start time`), m('td', `${timeToCode(sliceInfo.ts)}`)),
+ m('tr',
+ m('th', `Start time`),
+ m('td',
+ `${tpTimeToCode(sliceInfo.ts - globals.state.traceTime.start)}`)),
m('tr',
m('th', `Duration`),
m('td', this.computeDuration(sliceInfo.ts, sliceInfo.dur))),
@@ -172,8 +172,7 @@
trackId: trackId.toString(),
}));
- scrollToTrackAndTs(
- trackId, toNs(sliceInfo.ts + globals.state.traceTime.startSec), true);
+ scrollToTrackAndTs(trackId, sliceInfo.ts, true);
}
}
diff --git a/ui/src/frontend/slice_panel.ts b/ui/src/frontend/slice_panel.ts
index 17b4aeb..9d6f542 100644
--- a/ui/src/frontend/slice_panel.ts
+++ b/ui/src/frontend/slice_panel.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {timeToCode, toNs} from '../common/time';
+import {TPDuration, TPTime, tpTimeToCode} from '../common/time';
import {globals, SliceDetails} from './globals';
import {Panel} from './panel';
@@ -34,10 +34,9 @@
}
export abstract class SlicePanel extends Panel {
- protected computeDuration(ts: number, dur: number): string {
- return toNs(dur) === -1 ?
- `${globals.state.traceTime.endSec - ts} (Did not end)` :
- timeToCode(dur);
+ protected computeDuration(ts: TPTime, dur: TPDuration): string {
+ return dur === -1n ? `${globals.state.traceTime.end - ts} (Did not end)` :
+ tpTimeToCode(dur);
}
protected getProcessThreadDetails(sliceInfo: SliceDetails) {
diff --git a/ui/src/frontend/sql_types.ts b/ui/src/frontend/sql_types.ts
index f7135fa..b7e2df2 100644
--- a/ui/src/frontend/sql_types.ts
+++ b/ui/src/frontend/sql_types.ts
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {ColumnType} from 'src/common/query_result';
-import {fromNs, toNs} from '../common/time';
+import {TPTime} from '../common/time';
+
import {globals} from './globals';
// Type-safe aliases for various flavours of ints Trace Processor exposes
@@ -26,37 +26,19 @@
// Timestamp (in nanoseconds) in the same time domain as Trace Processor is
// exposing.
-export type TPTimestamp = bigint&{
+export type TPTimestamp = TPTime&{
__type: 'TPTimestamp'
}
-// Create a timestamp from a bigint in nanos.
-// Use this when we know the type is a bigint.
-export function timestampFromNanos(nanos: bigint) {
- return nanos as TPTimestamp;
-}
-
-// Create a timestamp from an arbitrary SQL value.
-// Throws if the value cannot be reasonably converted to a timestamp.
-// Assumes the input will be in units of nanoseconds.
-export function timestampFromSqlNanos(nanos: ColumnType): TPTimestamp {
- if (typeof nanos === 'bigint') {
- return nanos as TPTimestamp;
- } else if (typeof nanos === 'number') {
- // Note - this will throw if the number is something which cannot be
- // represented by an integer - i.e. decimals, infinity, or NaN.
- return BigInt(nanos) as TPTimestamp;
- } else {
- throw Error('Refusing to create TPTimestamp from unrelated type');
- }
+export function asTPTimestamp(v: bigint): TPTimestamp;
+export function asTPTimestamp(v?: bigint): TPTimestamp|undefined;
+export function asTPTimestamp(v?: bigint): TPTimestamp|undefined {
+ return v as (TPTimestamp | undefined);
}
// TODO: unify this with common/time.ts.
-// TODO(stevegolton): Return a bigint, or a new TPDuration object rather than
-// convert to number which could lose precision.
-export function toTraceTime(ts: TPTimestamp): number {
- const traceStartNs = toNs(globals.state.traceTime.startSec);
- return fromNs(Number(ts - BigInt(traceStartNs)));
+export function toTraceTime(ts: TPTimestamp): TPTime {
+ return ts - globals.state.traceTime.start;
}
// Unique id for a process, id into |process| table.
diff --git a/ui/src/frontend/thread_state.ts b/ui/src/frontend/thread_state.ts
index c7031f2..0bc4082 100644
--- a/ui/src/frontend/thread_state.ts
+++ b/ui/src/frontend/thread_state.ts
@@ -16,7 +16,11 @@
import {EngineProxy} from '../common/engine';
import {LONG, NUM, NUM_NULL, STR_NULL} from '../common/query_result';
import {translateState} from '../common/thread_state';
-import {fromNs, timeToCode} from '../common/time';
+import {
+ TPDuration,
+ TPTime,
+ tpTimeToCode,
+} from '../common/time';
import {copyToClipboard} from './clipboard';
import {globals} from './globals';
@@ -26,9 +30,6 @@
asUtid,
SchedSqlId,
ThreadStateSqlId,
- timestampFromNanos,
- toTraceTime,
- TPTimestamp,
} from './sql_types';
import {
constraintsToQueryFragment,
@@ -50,10 +51,10 @@
threadStateSqlId: ThreadStateSqlId;
// Id of the corresponding entry in the |sched| table.
schedSqlId?: SchedSqlId;
- // Timestamp of the beginning of this thread state in nanoseconds.
- ts: TPTimestamp;
+ // Timestamp of the the beginning of this thread state in nanoseconds.
+ ts: TPTime;
// Duration of this thread state in nanoseconds.
- dur: number;
+ dur: TPDuration;
// CPU id if this thread state corresponds to a thread running on the CPU.
cpu?: number;
// Human-readable name of this thread state.
@@ -90,7 +91,7 @@
threadStateSqlId: NUM,
schedSqlId: NUM_NULL,
ts: LONG,
- dur: NUM,
+ dur: LONG,
cpu: NUM_NULL,
state: STR_NULL,
blockedFunction: STR_NULL,
@@ -110,7 +111,7 @@
result.push({
threadStateSqlId: it.threadStateSqlId as ThreadStateSqlId,
schedSqlId: fromNumNull(it.schedSqlId) as (SchedSqlId | undefined),
- ts: timestampFromNanos(it.ts),
+ ts: it.ts,
dur: it.dur,
cpu: fromNumNull(it.cpu),
state: translateState(it.state || undefined, ioWait),
@@ -137,7 +138,7 @@
return result[0];
}
-export function goToSchedSlice(cpu: number, id: SchedSqlId, ts: TPTimestamp) {
+export function goToSchedSlice(cpu: number, id: SchedSqlId, ts: TPTime) {
let trackId: string|undefined;
for (const track of Object.values(globals.state.tracks)) {
if (track.kind === 'CpuSliceTrack' &&
@@ -149,15 +150,12 @@
return;
}
globals.makeSelection(Actions.selectSlice({id, trackId}));
- // TODO(stevegolton): scrollToTrackAndTs() should take a TPTimestamp
- scrollToTrackAndTs(trackId, Number(ts));
+ scrollToTrackAndTs(trackId, ts);
}
function stateToValue(
- state: string,
- cpu: number|undefined,
- id: SchedSqlId|undefined,
- ts: TPTimestamp): Value|null {
+ state: string, cpu: number|undefined, id: SchedSqlId|undefined, ts: TPTime):
+ Value|null {
if (!state) {
return null;
}
@@ -177,8 +175,9 @@
export function threadStateToDict(state: ThreadState): Dict {
const result: {[name: string]: Value|null} = {};
- result['Start time'] = value(timeToCode(toTraceTime(state.ts)));
- result['Duration'] = value(timeToCode(fromNs(state.dur)));
+ result['Start time'] =
+ value(tpTimeToCode(state.ts - globals.state.traceTime.start));
+ result['Duration'] = value(tpTimeToCode(state.dur));
result['State'] =
stateToValue(state.state, state.cpu, state.schedSqlId, state.ts);
result['Blocked function'] = maybeValue(state.blockedFunction);
diff --git a/ui/src/frontend/tickmark_panel.ts b/ui/src/frontend/tickmark_panel.ts
index 00612eb..f1579b9 100644
--- a/ui/src/frontend/tickmark_panel.ts
+++ b/ui/src/frontend/tickmark_panel.ts
@@ -19,6 +19,7 @@
import {TRACK_SHELL_WIDTH} from './css_constants';
import {globals} from './globals';
import {
+ getMaxMajorTicks,
TickGenerator,
TickType,
timeScaleForVisibleWindow,
@@ -32,14 +33,26 @@
}
renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {visibleWindowTime, visibleTimeScale} = globals.frontendLocalState;
ctx.fillStyle = '#999';
ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
- const relScale = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
- if (relScale.timeSpan.duration > 0 && relScale.widthPx > 0) {
- for (const {type, position} of new TickGenerator(relScale)) {
- if (type === TickType.MAJOR) ctx.fillRect(position, 0, 1, size.height);
+
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height);
+ ctx.clip();
+
+ const span = globals.frontendLocalState.visibleWindow.timestampSpan;
+ if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) {
+ const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH);
+ const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
+ for (const {type, time} of new TickGenerator(
+ span, maxMajorTicks, globals.state.traceTime.start)) {
+ const px = Math.floor(map.tpTimeToPx(time));
+ if (type === TickType.MAJOR) {
+ ctx.fillRect(px, 0, 1, size.height);
+ }
}
}
@@ -47,12 +60,13 @@
for (let i = 0; i < data.tsStarts.length; i++) {
const tStart = data.tsStarts[i];
const tEnd = data.tsEnds[i];
- if (tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end) {
+ if (tEnd <= visibleWindowTime.start.seconds ||
+ tStart >= visibleWindowTime.end.seconds) {
continue;
}
const rectStart =
- Math.max(timeScale.timeToPx(tStart), 0) + TRACK_SHELL_WIDTH;
- const rectEnd = timeScale.timeToPx(tEnd) + TRACK_SHELL_WIDTH;
+ Math.max(visibleTimeScale.secondsToPx(tStart), 0) + TRACK_SHELL_WIDTH;
+ const rectEnd = visibleTimeScale.secondsToPx(tEnd) + TRACK_SHELL_WIDTH;
ctx.fillStyle = '#ffe263';
ctx.fillRect(
Math.floor(rectStart),
@@ -61,16 +75,21 @@
size.height);
}
const index = globals.state.searchIndex;
- const startSec = fromNs(globals.currentSearchResults.tsStarts[index]);
- const triangleStart =
- Math.max(timeScale.timeToPx(startSec), 0) + TRACK_SHELL_WIDTH;
- ctx.fillStyle = '#000';
- ctx.beginPath();
- ctx.moveTo(triangleStart, size.height);
- ctx.lineTo(triangleStart - 3, 0);
- ctx.lineTo(triangleStart + 3, 0);
- ctx.lineTo(triangleStart, size.height);
- ctx.fill();
- ctx.closePath();
+ if (index !== -1) {
+ const startSec = fromNs(globals.currentSearchResults.tsStarts[index]);
+ const triangleStart =
+ Math.max(visibleTimeScale.secondsToPx(startSec), 0) +
+ TRACK_SHELL_WIDTH;
+ ctx.fillStyle = '#000';
+ ctx.beginPath();
+ ctx.moveTo(triangleStart, size.height);
+ ctx.lineTo(triangleStart - 3, 0);
+ ctx.lineTo(triangleStart + 3, 0);
+ ctx.lineTo(triangleStart, size.height);
+ ctx.fill();
+ ctx.closePath();
+ }
+
+ ctx.restore();
}
}
diff --git a/ui/src/frontend/time_axis_panel.ts b/ui/src/frontend/time_axis_panel.ts
index 3f6dc64..4819d54 100644
--- a/ui/src/frontend/time_axis_panel.ts
+++ b/ui/src/frontend/time_axis_panel.ts
@@ -14,11 +14,15 @@
import m from 'mithril';
-import {timeToString} from '../common/time';
+import {
+ tpTimeToSeconds,
+ tpTimeToString,
+} from '../common/time';
import {TRACK_SHELL_WIDTH} from './css_constants';
import {globals} from './globals';
import {
+ getMaxMajorTicks,
TickGenerator,
TickType,
timeScaleForVisibleWindow,
@@ -35,21 +39,33 @@
ctx.font = '10px Roboto Condensed';
ctx.textAlign = 'left';
- const startTime = timeToString(globals.state.traceTime.startSec);
+ const startTime = tpTimeToString(globals.state.traceTime.start);
ctx.fillText(startTime + ' +', 6, 11);
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height);
+ ctx.clip();
+
// Draw time axis.
- const timeScale = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
- if (timeScale.timeSpan.duration > 0 && timeScale.widthPx > 0) {
- const tickGen = new TickGenerator(timeScale);
- for (const {type, time, position} of tickGen) {
+ const span = globals.frontendLocalState.visibleWindow.timestampSpan;
+ if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) {
+ const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH);
+ const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
+ const tickGen =
+ new TickGenerator(span, maxMajorTicks, globals.state.traceTime.start);
+ for (const {type, time} of tickGen) {
+ const position = Math.floor(map.tpTimeToPx(time));
+ const sec = tpTimeToSeconds(time - globals.state.traceTime.start);
if (type === TickType.MAJOR) {
ctx.fillRect(position, 0, 1, size.height);
- ctx.fillText(time.toFixed(tickGen.digits) + ' s', position + 5, 10);
+ ctx.fillText(sec.toFixed(tickGen.digits) + ' s', position + 5, 10);
}
}
}
+ ctx.restore();
+
ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
}
}
diff --git a/ui/src/frontend/time_scale.ts b/ui/src/frontend/time_scale.ts
index 6f0307a..7804348 100644
--- a/ui/src/frontend/time_scale.ts
+++ b/ui/src/frontend/time_scale.ts
@@ -12,95 +12,92 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {assertFalse, assertTrue} from '../base/logging';
-import {TimeSpan} from '../common/time';
+import {assertTrue} from '../base/logging';
+import {
+ HighPrecisionTime,
+ HighPrecisionTimeSpan,
+} from '../common/high_precision_time';
+import {Span} from '../common/time';
+import {
+ TPDuration,
+ TPTime,
+} from '../common/time';
-const MAX_ZOOM_SPAN_SEC = 1e-8; // 10 ns.
-
-/**
- * Defines a mapping between number and seconds for the entire application.
- * Linearly scales time values from boundsMs to pixel values in boundsPx and
- * back.
- */
export class TimeScale {
- private timeBounds: TimeSpan;
- private _startPx: number;
- private _endPx: number;
- private secPerPx = 0;
+ private _start: HighPrecisionTime;
+ private _durationNanos: number;
+ readonly pxSpan: PxSpan;
+ private _nanosPerPx = 0;
+ private _startSec: number;
- constructor(timeBounds: TimeSpan, boundsPx: [number, number]) {
- this.timeBounds = timeBounds;
- this._startPx = boundsPx[0];
- this._endPx = boundsPx[1];
- this.updateSlope();
+ constructor(start: HighPrecisionTime, durationNanos: number, pxSpan: PxSpan) {
+ // TODO(stevegolton): Ensure duration & pxSpan > 0.
+ // assertTrue(pxSpan.start < pxSpan.end, 'Px start >= end');
+ // assertTrue(durationNanos < 0, 'Duration <= 0');
+ this.pxSpan = pxSpan;
+ this._start = start;
+ this._durationNanos = durationNanos;
+ if (durationNanos <= 0 || pxSpan.delta <= 0) {
+ this._nanosPerPx = 1;
+ } else {
+ this._nanosPerPx = durationNanos / (pxSpan.delta);
+ }
+ this._startSec = this._start.seconds;
}
- private updateSlope() {
- this.secPerPx = this.timeBounds.duration / (this._endPx - this._startPx);
+ get timeSpan(): Span<HighPrecisionTime> {
+ const end = this._start.addNanos(this._durationNanos);
+ return new HighPrecisionTimeSpan(this._start, end);
}
- deltaTimeToPx(time: number): number {
- return Math.round(time / this.secPerPx);
+ tpTimeToPx(ts: TPTime): number {
+ // WARNING: Number(bigint) can be surprisingly slow. Avoid in hotpath.
+ const timeOffsetNanos = Number(ts - this._start.base) - this._start.offset;
+ return this.pxSpan.start + timeOffsetNanos / this._nanosPerPx;
}
- timeToPx(time: number): number {
- return this._startPx + (time - this.timeBounds.start) / this.secPerPx;
+ secondsToPx(seconds: number): number {
+ const timeOffset = (seconds - this._startSec) * 1e9;
+ return this.pxSpan.start + timeOffset / this._nanosPerPx;
}
- pxToTime(px: number): number {
- return this.timeBounds.start + (px - this._startPx) * this.secPerPx;
+ hpTimeToPx(time: HighPrecisionTime): number {
+ const timeOffsetNanos = time.subtract(this._start).nanos;
+ return this.pxSpan.start + timeOffsetNanos / this._nanosPerPx;
}
- deltaPxToDuration(px: number): number {
- return px * this.secPerPx;
+ // Convert pixels to a high precision time object, which can be futher
+ // converted to other time formats.
+ pxToHpTime(px: number): HighPrecisionTime {
+ const offsetNanos = (px - this.pxSpan.start) * this._nanosPerPx;
+ return this._start.addNanos(offsetNanos);
}
- setTimeBounds(timeBounds: TimeSpan) {
- this.timeBounds = timeBounds;
- this.updateSlope();
+ durationToPx(dur: TPDuration): number {
+ // WARNING: Number(bigint) can be surprisingly slow. Avoid in hotpath.
+ return Number(dur) / this._nanosPerPx;
}
- setLimitsPx(pxStart: number, pxEnd: number) {
- assertFalse(pxStart === pxEnd);
- assertTrue(pxStart >= 0 && pxEnd >= 0);
- this._startPx = pxStart;
- this._endPx = pxEnd;
- this.updateSlope();
- }
-
- timeInBounds(time: number): boolean {
- return this.timeBounds.isInBounds(time);
- }
-
- get startPx(): number {
- return this._startPx;
- }
-
- get endPx(): number {
- return this._endPx;
- }
-
- get widthPx(): number {
- return this._endPx - this._startPx;
- }
-
- get timeSpan(): TimeSpan {
- return this.timeBounds;
+ pxDeltaToDuration(pxDelta: number): HighPrecisionTime {
+ const time = pxDelta * this._nanosPerPx;
+ return HighPrecisionTime.fromNanos(time);
}
}
-export function computeZoom(
- scale: TimeScale, span: TimeSpan, zoomFactor: number, zoomPx: number):
- TimeSpan {
- const startPx = scale.startPx;
- const endPx = scale.endPx;
- const deltaPx = endPx - startPx;
- const deltaTime = span.end - span.start;
- const newDeltaTime = Math.max(deltaTime * zoomFactor, MAX_ZOOM_SPAN_SEC);
- const clampedZoomPx = Math.max(startPx, Math.min(endPx, zoomPx));
- const zoomTime = scale.pxToTime(clampedZoomPx);
- const r = (clampedZoomPx - startPx) / deltaPx;
- const newStartTime = zoomTime - newDeltaTime * r;
- const newEndTime = newStartTime + newDeltaTime;
- return new TimeSpan(newStartTime, newEndTime);
+export class PxSpan {
+ constructor(private _start: number, private _end: number) {
+ assertTrue(_start <= _end, 'PxSpan start > end');
+ }
+
+ get start(): number {
+ return this._start;
+ }
+
+ get end(): number {
+ return this._end;
+ }
+
+ get delta(): number {
+ return this._end - this._start;
+ }
}
diff --git a/ui/src/frontend/time_scale_unittest.ts b/ui/src/frontend/time_scale_unittest.ts
index 7a1be03..f7046de 100644
--- a/ui/src/frontend/time_scale_unittest.ts
+++ b/ui/src/frontend/time_scale_unittest.ts
@@ -12,66 +12,62 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {TimeSpan} from '../common/time';
+import {HighPrecisionTime} from '../common/high_precision_time';
-import {computeZoom, TimeScale} from './time_scale';
+import {PxSpan, TimeScale} from './time_scale';
-test('time scale to work', () => {
- const scale = new TimeScale(new TimeSpan(0, 100), [200, 1000]);
+describe('TimeScale', () => {
+ const ts =
+ new TimeScale(new HighPrecisionTime(40n), 100, new PxSpan(200, 1000));
- expect(scale.timeToPx(0)).toEqual(200);
- expect(scale.timeToPx(100)).toEqual(1000);
- expect(scale.timeToPx(50)).toEqual(600);
+ it('converts timescales to pixels', () => {
+ expect(ts.tpTimeToPx(40n)).toEqual(200);
+ expect(ts.tpTimeToPx(140n)).toEqual(1000);
+ expect(ts.tpTimeToPx(90n)).toEqual(600);
- expect(scale.pxToTime(200)).toEqual(0);
- expect(scale.pxToTime(1000)).toEqual(100);
- expect(scale.pxToTime(600)).toEqual(50);
+ expect(ts.tpTimeToPx(240n)).toEqual(1800);
+ expect(ts.tpTimeToPx(-60n)).toEqual(-600);
+ });
- expect(scale.deltaPxToDuration(400)).toEqual(50);
+ it('converts pixels to HPTime objects', () => {
+ let result = ts.pxToHpTime(200);
+ expect(result.base).toEqual(40n);
+ expect(result.offset).toBeCloseTo(0);
- expect(scale.timeInBounds(50)).toEqual(true);
- expect(scale.timeInBounds(0)).toEqual(true);
- expect(scale.timeInBounds(100)).toEqual(true);
- expect(scale.timeInBounds(-1)).toEqual(false);
- expect(scale.timeInBounds(101)).toEqual(false);
-});
+ result = ts.pxToHpTime(1000);
+ expect(result.base).toEqual(140n);
+ expect(result.offset).toBeCloseTo(0);
+ result = ts.pxToHpTime(600);
+ expect(result.base).toEqual(90n);
+ expect(result.offset).toBeCloseTo(0);
-test('time scale to be updatable', () => {
- const scale = new TimeScale(new TimeSpan(0, 100), [100, 1000]);
+ result = ts.pxToHpTime(1800);
+ expect(result.base).toEqual(240n);
+ expect(result.offset).toBeCloseTo(0);
- expect(scale.timeToPx(0)).toEqual(100);
+ result = ts.pxToHpTime(-600);
+ expect(result.base).toEqual(-60n);
+ expect(result.offset).toBeCloseTo(0);
+ });
- scale.setLimitsPx(200, 1000);
- expect(scale.timeToPx(0)).toEqual(200);
- expect(scale.timeToPx(100)).toEqual(1000);
+ it('converts durations to pixels', () => {
+ expect(ts.durationToPx(0n)).toEqual(0);
+ expect(ts.durationToPx(1n)).toEqual(8);
+ expect(ts.durationToPx(1000n)).toEqual(8000);
+ });
- scale.setTimeBounds(new TimeSpan(0, 200));
- expect(scale.timeToPx(0)).toEqual(200);
- expect(scale.timeToPx(100)).toEqual(600);
- expect(scale.timeToPx(200)).toEqual(1000);
-});
+ it('converts pxDeltaToDurations to HPTime durations', () => {
+ let result = ts.pxDeltaToDuration(0);
+ expect(result.base).toEqual(0n);
+ expect(result.offset).toBeCloseTo(0);
-test('it zooms', () => {
- const span = new TimeSpan(0, 20);
- const scale = new TimeScale(span, [0, 100]);
- const newSpan = computeZoom(scale, span, 0.5, 50);
- expect(newSpan.start).toEqual(5);
- expect(newSpan.end).toEqual(15);
-});
+ result = ts.pxDeltaToDuration(1);
+ expect(result.base).toEqual(0n);
+ expect(result.offset).toBeCloseTo(0.125);
-test('it zooms an offset scale and span', () => {
- const span = new TimeSpan(1000, 1020);
- const scale = new TimeScale(span, [200, 300]);
- const newSpan = computeZoom(scale, span, 0.5, 250);
- expect(newSpan.start).toEqual(1005);
- expect(newSpan.end).toEqual(1015);
-});
-
-test('it clamps zoom in', () => {
- const span = new TimeSpan(1000, 1040);
- const scale = new TimeScale(span, [200, 300]);
- const newSpan = computeZoom(scale, span, 0.0000000001, 225);
- expect((newSpan.end - newSpan.start) / 2 + newSpan.start).toBeCloseTo(1010);
- expect(newSpan.end - newSpan.start).toBeCloseTo(1e-8);
+ result = ts.pxDeltaToDuration(100);
+ expect(result.base).toEqual(12n);
+ expect(result.offset).toBeCloseTo(0.5);
+ });
});
diff --git a/ui/src/frontend/time_selection_panel.ts b/ui/src/frontend/time_selection_panel.ts
index 20f1c53..5711e6a 100644
--- a/ui/src/frontend/time_selection_panel.ts
+++ b/ui/src/frontend/time_selection_panel.ts
@@ -13,9 +13,13 @@
// limitations under the License.
import m from 'mithril';
+import {BigintMath} from '../base/bigint_math';
-import {timeToString} from '../common/time';
-import {TimeSpan} from '../common/time';
+import {Span, tpTimeToString} from '../common/time';
+import {
+ TPTime,
+ TPTimeSpan,
+} from '../common/time';
import {
BACKGROUND_COLOR,
@@ -24,6 +28,7 @@
} from './css_constants';
import {globals} from './globals';
import {
+ getMaxMajorTicks,
TickGenerator,
TickType,
timeScaleForVisibleWindow,
@@ -48,7 +53,7 @@
ctx.fillStyle = FOREGROUND_COLOR;
const xLeft = Math.floor(target.x);
- const xRight = Math.ceil(target.x + target.width);
+ const xRight = Math.floor(target.x + target.width);
const yMid = Math.floor(target.height / 2 + target.y);
const xWidth = xRight - xLeft;
@@ -130,11 +135,21 @@
renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
ctx.fillStyle = '#999';
ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
- const scale = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
- if (scale.timeSpan.duration > 0 && scale.widthPx > 0) {
- for (const {position, type} of new TickGenerator(scale)) {
+
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height);
+ ctx.clip();
+
+ const span = globals.frontendLocalState.visibleWindow.timestampSpan;
+ if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) {
+ const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH);
+ const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
+ for (const {type, time} of new TickGenerator(
+ span, maxMajorTicks, globals.state.traceTime.start)) {
+ const px = Math.floor(map.tpTimeToPx(time));
if (type === TickType.MAJOR) {
- ctx.fillRect(position, 0, 1, size.height);
+ ctx.fillRect(px, 0, 1, size.height);
}
}
}
@@ -142,17 +157,17 @@
const localArea = globals.frontendLocalState.selectedArea;
const selection = globals.state.currentSelection;
if (localArea !== undefined) {
- const start = Math.min(localArea.startSec, localArea.endSec);
- const end = Math.max(localArea.startSec, localArea.endSec);
- this.renderSpan(ctx, size, new TimeSpan(start, end));
+ const start = BigintMath.min(localArea.start, localArea.end);
+ const end = BigintMath.max(localArea.start, localArea.end);
+ this.renderSpan(ctx, size, new TPTimeSpan(start, end));
} else if (selection !== null && selection.kind === 'AREA') {
const selectedArea = globals.state.areas[selection.areaId];
- const start = Math.min(selectedArea.startSec, selectedArea.endSec);
- const end = Math.max(selectedArea.startSec, selectedArea.endSec);
- this.renderSpan(ctx, size, new TimeSpan(start, end));
+ const start = BigintMath.min(selectedArea.start, selectedArea.end);
+ const end = BigintMath.max(selectedArea.start, selectedArea.end);
+ this.renderSpan(ctx, size, new TPTimeSpan(start, end));
}
- if (globals.state.hoverCursorTimestamp !== -1) {
+ if (globals.state.hoverCursorTimestamp !== -1n) {
this.renderHover(ctx, size, globals.state.hoverCursorTimestamp);
}
@@ -162,27 +177,29 @@
if (note.noteType === 'AREA' && !noteIsSelected) {
const selectedArea = globals.state.areas[note.areaId];
this.renderSpan(
- ctx,
- size,
- new TimeSpan(selectedArea.startSec, selectedArea.endSec));
+ ctx, size, new TPTimeSpan(selectedArea.start, selectedArea.end));
}
}
+
+ ctx.restore();
}
- renderHover(ctx: CanvasRenderingContext2D, size: PanelSize, ts: number) {
- const timeScale = globals.frontendLocalState.timeScale;
- const xPos = TRACK_SHELL_WIDTH + Math.floor(timeScale.timeToPx(ts));
- const offsetTime = timeToString(ts - globals.state.traceTime.startSec);
- const timeFromStart = timeToString(ts);
+ renderHover(ctx: CanvasRenderingContext2D, size: PanelSize, ts: TPTime) {
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const xPos =
+ TRACK_SHELL_WIDTH + Math.floor(visibleTimeScale.tpTimeToPx(ts));
+ const offsetTime = tpTimeToString(ts - globals.state.traceTime.start);
+ const timeFromStart = tpTimeToString(ts);
const label = `${offsetTime} (${timeFromStart})`;
drawIBar(ctx, xPos, this.bounds(size), label);
}
- renderSpan(ctx: CanvasRenderingContext2D, size: PanelSize, span: TimeSpan) {
- const timeScale = globals.frontendLocalState.timeScale;
- const xLeft = timeScale.timeToPx(span.start);
- const xRight = timeScale.timeToPx(span.end);
- const label = timeToString(span.duration);
+ renderSpan(
+ ctx: CanvasRenderingContext2D, size: PanelSize, span: Span<TPTime>) {
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const xLeft = visibleTimeScale.tpTimeToPx(span.start);
+ const xRight = visibleTimeScale.tpTimeToPx(span.end);
+ const label = tpTimeToString(span.duration);
drawHBar(
ctx,
{
diff --git a/ui/src/frontend/trace_converter.ts b/ui/src/frontend/trace_converter.ts
index ca4ced3..0f5ca69 100644
--- a/ui/src/frontend/trace_converter.ts
+++ b/ui/src/frontend/trace_converter.ts
@@ -17,6 +17,7 @@
ConversionJobName,
ConversionJobStatus,
} from '../common/conversion_jobs';
+import {TPTime} from '../common/time';
import {download} from './clipboard';
import {maybeShowErrorDialog} from './error_dialog';
@@ -106,7 +107,7 @@
}
export function convertTraceToPprofAndDownload(
- trace: Blob, pid: number, ts: number) {
+ trace: Blob, pid: number, ts: TPTime) {
makeWorkerAndPost({
kind: 'ConvertTraceToPprof',
trace,
diff --git a/ui/src/frontend/track.ts b/ui/src/frontend/track.ts
index 2d5ab81..e826317 100644
--- a/ui/src/frontend/track.ts
+++ b/ui/src/frontend/track.ts
@@ -130,9 +130,11 @@
render(ctx: CanvasRenderingContext2D) {
globals.frontendLocalState.addVisibleTrack(this.trackState.id);
if (this.data() === undefined && !this.frontendOnly) {
- const {visibleWindowTime, timeScale} = globals.frontendLocalState;
- const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
- const endPx = Math.ceil(timeScale.timeToPx(visibleWindowTime.end));
+ const {visibleWindowTime, visibleTimeScale} = globals.frontendLocalState;
+ const startPx =
+ Math.floor(visibleTimeScale.hpTimeToPx(visibleWindowTime.start));
+ const endPx =
+ Math.ceil(visibleTimeScale.hpTimeToPx(visibleWindowTime.end));
checkerboard(ctx, this.getHeight(), startPx, endPx);
} else {
this.renderCanvas(ctx);
@@ -175,7 +177,7 @@
y -= 10;
// Ensure the box is on screen:
- const endPx = globals.frontendLocalState.timeScale.endPx;
+ const endPx = globals.frontendLocalState.visibleTimeScale.pxSpan.end;
if (x + width > endPx) {
x -= x + width - endPx;
}
diff --git a/ui/src/frontend/track_cache.ts b/ui/src/frontend/track_cache.ts
index 049cbf4..2adbd0c 100644
--- a/ui/src/frontend/track_cache.ts
+++ b/ui/src/frontend/track_cache.ts
@@ -52,6 +52,7 @@
// In other words the normal window is a superset of the data of the
// non-normal window at a higher resolution. Normalization is used to
// avoid re-fetching data on tiny zooms/moves/resizes.
+// TODO(stevegolton): Convert to bigint timestamps.
export class CacheKey {
readonly startNs: number;
readonly endNs: number;
diff --git a/ui/src/frontend/track_group_panel.ts b/ui/src/frontend/track_group_panel.ts
index c9d109f..dbab7f7 100644
--- a/ui/src/frontend/track_group_panel.ts
+++ b/ui/src/frontend/track_group_panel.ts
@@ -187,18 +187,17 @@
}
highlightIfTrackSelected(ctx: CanvasRenderingContext2D, size: PanelSize) {
- const localState = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.frontendLocalState;
const selection = globals.state.currentSelection;
if (!selection || selection.kind !== 'AREA') return;
const selectedArea = globals.state.areas[selection.areaId];
+ const selectedAreaDuration = selectedArea.end - selectedArea.start;
if (selectedArea.tracks.includes(this.trackGroupId)) {
ctx.fillStyle = 'rgba(131, 152, 230, 0.3)';
ctx.fillRect(
- localState.timeScale.timeToPx(selectedArea.startSec) +
- this.shellWidth,
+ visibleTimeScale.tpTimeToPx(selectedArea.start) + this.shellWidth,
0,
- localState.timeScale.deltaTimeToPx(
- selectedArea.endSec - selectedArea.startSec),
+ visibleTimeScale.durationToPx(selectedAreaDuration),
size.height);
}
}
@@ -227,20 +226,20 @@
this.highlightIfTrackSelected(ctx, size);
- const localState = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.frontendLocalState;
// Draw vertical line when hovering on the notes panel.
- if (globals.state.hoveredNoteTimestamp !== -1) {
+ if (globals.state.hoveredNoteTimestamp !== -1n) {
drawVerticalLineAtTime(
ctx,
- localState.timeScale,
+ visibleTimeScale,
globals.state.hoveredNoteTimestamp,
size.height,
`#aaa`);
}
- if (globals.state.hoverCursorTimestamp !== -1) {
+ if (globals.state.hoverCursorTimestamp !== -1n) {
drawVerticalLineAtTime(
ctx,
- localState.timeScale,
+ visibleTimeScale,
globals.state.hoverCursorTimestamp,
size.height,
`#344596`);
@@ -251,7 +250,7 @@
globals.sliceDetails.wakeupTs !== undefined) {
drawVerticalLineAtTime(
ctx,
- localState.timeScale,
+ visibleTimeScale,
globals.sliceDetails.wakeupTs,
size.height,
`black`);
@@ -265,21 +264,21 @@
'rgba(' + hex.rgb(note.color.substr(1)).toString() + ', 0.65)';
drawVerticalLineAtTime(
ctx,
- localState.timeScale,
- globals.state.areas[note.areaId].startSec,
+ visibleTimeScale,
+ globals.state.areas[note.areaId].start,
size.height,
transparentNoteColor,
1);
drawVerticalLineAtTime(
ctx,
- localState.timeScale,
- globals.state.areas[note.areaId].endSec,
+ visibleTimeScale,
+ globals.state.areas[note.areaId].end,
size.height,
transparentNoteColor,
1);
} else if (note.noteType === 'DEFAULT') {
drawVerticalLineAtTime(
- ctx, localState.timeScale, note.timestamp, size.height, note.color);
+ ctx, visibleTimeScale, note.timestamp, size.height, note.color);
}
}
}
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index 1ab998f..278b73d 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -95,7 +95,6 @@
`.track-shell[draggable=true]`,
{
class: `${highlightClass} ${dragClass} ${dropClass}`,
- onmousedown: this.onmousedown.bind(this),
ondragstart: this.ondragstart.bind(this),
ondragend: this.ondragend.bind(this),
ondragover: this.ondragover.bind(this),
@@ -145,12 +144,6 @@
''));
}
- onmousedown(e: MouseEvent) {
- // Prevent that the click is intercepted by the PanAndZoomHandler and that
- // we start panning while dragging.
- e.stopPropagation();
- }
-
ondragstart(e: DragEvent) {
const dataTransfer = e.dataTransfer;
if (dataTransfer === null) return;
@@ -158,7 +151,6 @@
globals.rafScheduler.scheduleFullRedraw();
dataTransfer.setData('perfetto/track', `${this.attrs!.trackState.id}`);
dataTransfer.setDragImage(new Image(), 0, 0);
- e.stopImmediatePropagation();
}
ondragend() {
@@ -370,20 +362,20 @@
}
highlightIfTrackSelected(ctx: CanvasRenderingContext2D, size: PanelSize) {
- const localState = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.frontendLocalState;
const selection = globals.state.currentSelection;
const trackState = this.trackState;
if (!selection || selection.kind !== 'AREA' || trackState === undefined) {
return;
}
const selectedArea = globals.state.areas[selection.areaId];
+ const selectedAreaDuration = selectedArea.end - selectedArea.start;
if (selectedArea.tracks.includes(trackState.id)) {
- const timeScale = localState.timeScale;
ctx.fillStyle = SELECTION_FILL_COLOR;
ctx.fillRect(
- timeScale.timeToPx(selectedArea.startSec) + TRACK_SHELL_WIDTH,
+ visibleTimeScale.tpTimeToPx(selectedArea.start) + TRACK_SHELL_WIDTH,
0,
- timeScale.deltaTimeToPx(selectedArea.endSec - selectedArea.startSec),
+ visibleTimeScale.durationToPx(selectedAreaDuration),
size.height);
}
}
@@ -404,20 +396,20 @@
this.highlightIfTrackSelected(ctx, size);
- const localState = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.frontendLocalState;
// Draw vertical line when hovering on the notes panel.
- if (globals.state.hoveredNoteTimestamp !== -1) {
+ if (globals.state.hoveredNoteTimestamp !== -1n) {
drawVerticalLineAtTime(
ctx,
- localState.timeScale,
+ visibleTimeScale,
globals.state.hoveredNoteTimestamp,
size.height,
`#aaa`);
}
- if (globals.state.hoverCursorTimestamp !== -1) {
+ if (globals.state.hoverCursorTimestamp !== -1n) {
drawVerticalLineAtTime(
ctx,
- localState.timeScale,
+ visibleTimeScale,
globals.state.hoverCursorTimestamp,
size.height,
`#344596`);
@@ -428,7 +420,7 @@
globals.sliceDetails.wakeupTs !== undefined) {
drawVerticalLineAtTime(
ctx,
- localState.timeScale,
+ visibleTimeScale,
globals.sliceDetails.wakeupTs,
size.height,
`black`);
@@ -442,21 +434,21 @@
'rgba(' + hex.rgb(note.color.substr(1)).toString() + ', 0.65)';
drawVerticalLineAtTime(
ctx,
- localState.timeScale,
- globals.state.areas[note.areaId].startSec,
+ visibleTimeScale,
+ globals.state.areas[note.areaId].start,
size.height,
transparentNoteColor,
1);
drawVerticalLineAtTime(
ctx,
- localState.timeScale,
- globals.state.areas[note.areaId].endSec,
+ visibleTimeScale,
+ globals.state.areas[note.areaId].end,
size.height,
transparentNoteColor,
1);
} else if (note.noteType === 'DEFAULT') {
drawVerticalLineAtTime(
- ctx, localState.timeScale, note.timestamp, size.height, note.color);
+ ctx, visibleTimeScale, note.timestamp, size.height, note.color);
}
}
}
diff --git a/ui/src/frontend/vertical_line_helper.ts b/ui/src/frontend/vertical_line_helper.ts
index b1e2cfc..353d166 100644
--- a/ui/src/frontend/vertical_line_helper.ts
+++ b/ui/src/frontend/vertical_line_helper.ts
@@ -12,18 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {TPTime} from '../common/time';
import {TRACK_SHELL_WIDTH} from './css_constants';
import {TimeScale} from './time_scale';
-export function drawVerticalLineAtTime(ctx: CanvasRenderingContext2D,
- timeScale: TimeScale,
- time: number,
- height: number,
- color: string,
- lineWidth = 2) {
- const xPos = TRACK_SHELL_WIDTH + Math.floor(timeScale.timeToPx(time));
- drawVerticalLine(ctx, xPos, height, color, lineWidth);
- }
+export function drawVerticalLineAtTime(
+ ctx: CanvasRenderingContext2D,
+ timeScale: TimeScale,
+ time: TPTime,
+ height: number,
+ color: string,
+ lineWidth = 2) {
+ const xPos = TRACK_SHELL_WIDTH + Math.floor(timeScale.tpTimeToPx(time));
+ drawVerticalLine(ctx, xPos, height, color, lineWidth);
+}
function drawVerticalLine(ctx: CanvasRenderingContext2D,
xPos: number,
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index d3651e7..1a9e096 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -13,10 +13,10 @@
// limitations under the License.
import m from 'mithril';
+import {BigintMath} from '../base/bigint_math';
import {Actions} from '../common/actions';
import {featureFlags} from '../common/feature_flags';
-import {TimeSpan} from '../common/time';
import {TRACK_SHELL_WIDTH} from './css_constants';
import {DetailsPanel} from './details_panel';
@@ -28,7 +28,6 @@
import {AnyAttrsVnode, PanelContainer} from './panel_container';
import {TickmarkPanel} from './tickmark_panel';
import {TimeAxisPanel} from './time_axis_panel';
-import {computeZoom} from './time_scale';
import {TimeSelectionPanel} from './time_selection_panel';
import {DISMISSED_PANNING_HINT_KEY} from './topbar';
import {TrackGroupPanel} from './track_group_panel';
@@ -53,8 +52,9 @@
const area = globals.frontendLocalState.selectedArea ?
globals.frontendLocalState.selectedArea :
globals.state.areas[selection.areaId];
- const start = globals.frontendLocalState.timeScale.timeToPx(area.startSec);
- const end = globals.frontendLocalState.timeScale.timeToPx(area.endSec);
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const start = visibleTimeScale.tpTimeToPx(area.start);
+ const end = visibleTimeScale.tpTimeToPx(area.end);
const startDrag = mousePos - TRACK_SHELL_WIDTH;
const startDistance = Math.abs(start - startDrag);
const endDistance = Math.abs(end - startDrag);
@@ -119,21 +119,14 @@
element: panZoomEl,
contentOffsetX: SIDEBAR_WIDTH,
onPanned: (pannedPx: number) => {
+ const {
+ visibleTimeScale,
+ } = globals.frontendLocalState;
+
this.keepCurrentSelection = true;
- const traceTime = globals.state.traceTime;
- const vizTime = globals.frontendLocalState.visibleWindowTime;
- const origDelta = vizTime.duration;
- const tDelta = frontendLocalState.timeScale.deltaPxToDuration(pannedPx);
- let tStart = vizTime.start + tDelta;
- let tEnd = vizTime.end + tDelta;
- if (tStart < traceTime.startSec) {
- tStart = traceTime.startSec;
- tEnd = tStart + origDelta;
- } else if (tEnd > traceTime.endSec) {
- tEnd = traceTime.endSec;
- tStart = tEnd - origDelta;
- }
- frontendLocalState.updateVisibleTime(new TimeSpan(tStart, tEnd));
+ const tDelta = visibleTimeScale.pxDeltaToDuration(pannedPx);
+ frontendLocalState.panVisibleWindow(tDelta);
+
// If the user has panned they no longer need the hint.
localStorage.setItem(DISMISSED_PANNING_HINT_KEY, 'true');
globals.rafScheduler.scheduleRedraw();
@@ -141,11 +134,10 @@
onZoomed: (zoomedPositionPx: number, zoomRatio: number) => {
// TODO(hjd): Avoid hardcoding TRACK_SHELL_WIDTH.
// TODO(hjd): Improve support for zooming in overview timeline.
- const span = frontendLocalState.visibleWindowTime;
- const scale = frontendLocalState.timeScale;
const zoomPx = zoomedPositionPx - TRACK_SHELL_WIDTH;
- const newSpan = computeZoom(scale, span, 1 - zoomRatio, zoomPx);
- frontendLocalState.updateVisibleTime(newSpan);
+ const rect = vnode.dom.getBoundingClientRect();
+ const centerPoint = zoomPx / (rect.width - TRACK_SHELL_WIDTH);
+ frontendLocalState.zoomVisibleWindow(1 - zoomRatio, centerPoint);
globals.rafScheduler.scheduleRedraw();
},
editSelection: (currentPx: number) => {
@@ -159,7 +151,7 @@
currentY: number,
editing: boolean) => {
const traceTime = globals.state.traceTime;
- const scale = frontendLocalState.timeScale;
+ const {visibleTimeScale} = frontendLocalState;
this.keepCurrentSelection = true;
if (editing) {
const selection = globals.state.currentSelection;
@@ -167,33 +159,40 @@
const area = globals.frontendLocalState.selectedArea ?
globals.frontendLocalState.selectedArea :
globals.state.areas[selection.areaId];
- let newTime = scale.pxToTime(currentX - TRACK_SHELL_WIDTH);
+ let newTime =
+ visibleTimeScale.pxToHpTime(currentX - TRACK_SHELL_WIDTH)
+ .toTPTime();
// Have to check again for when one boundary crosses over the other.
const curBoundary = onTimeRangeBoundary(prevX);
if (curBoundary == null) return;
- const keepTime =
- curBoundary === 'START' ? area.endSec : area.startSec;
+ const keepTime = curBoundary === 'START' ? area.end : area.start;
// Don't drag selection outside of current screen.
if (newTime < keepTime) {
- newTime = Math.max(newTime, scale.pxToTime(scale.startPx));
+ newTime = BigintMath.max(
+ newTime, visibleTimeScale.timeSpan.start.toTPTime());
} else {
- newTime = Math.min(newTime, scale.pxToTime(scale.endPx));
+ newTime = BigintMath.max(
+ newTime, visibleTimeScale.timeSpan.end.toTPTime());
}
// When editing the time range we always use the saved tracks,
// since these will not change.
frontendLocalState.selectArea(
- Math.max(Math.min(keepTime, newTime), traceTime.startSec),
- Math.min(Math.max(keepTime, newTime), traceTime.endSec),
+ BigintMath.max(
+ BigintMath.min(keepTime, newTime), traceTime.start),
+ BigintMath.min(
+ BigintMath.max(keepTime, newTime), traceTime.end),
globals.state.areas[selection.areaId].tracks);
}
} else {
let startPx = Math.min(dragStartX, currentX) - TRACK_SHELL_WIDTH;
let endPx = Math.max(dragStartX, currentX) - TRACK_SHELL_WIDTH;
if (startPx < 0 && endPx < 0) return;
- startPx = Math.max(startPx, scale.startPx);
- endPx = Math.min(endPx, scale.endPx);
+ startPx = Math.max(startPx, visibleTimeScale.pxSpan.start);
+ endPx = Math.min(endPx, visibleTimeScale.pxSpan.end);
frontendLocalState.selectArea(
- scale.pxToTime(startPx), scale.pxToTime(endPx));
+ visibleTimeScale.pxToHpTime(startPx).toTPTime('floor'),
+ visibleTimeScale.pxToHpTime(endPx).toTPTime('ceil'),
+ );
frontendLocalState.areaY.start = dragStartY;
frontendLocalState.areaY.end = currentY;
}
@@ -271,6 +270,9 @@
m('.pan-and-zoom-content',
{
onclick: () => {
+ // TODO(stevegolton): Make it possible to click buttons and
+ // things on this element without deselecting the selected
+ // element!
// We don't want to deselect when panning/drag selecting.
if (this.keepCurrentSelection) {
this.keepCurrentSelection = false;
diff --git a/ui/src/frontend/widgets/button.ts b/ui/src/frontend/widgets/button.ts
index 6c90c2e..ac86e13 100644
--- a/ui/src/frontend/widgets/button.ts
+++ b/ui/src/frontend/widgets/button.ts
@@ -15,6 +15,7 @@
import m from 'mithril';
import {classNames} from '../classnames';
import {Icon} from './icon';
+import {Popup} from './popup';
interface CommonAttrs {
// Always show the button as if the "active" pseudo class were applied, which
@@ -37,6 +38,9 @@
rightIcon?: string;
// List of space separated class names forwarded to the icon.
className?: string;
+ // Allow clicking this button to close parent popups.
+ // Defaults to false.
+ dismissPopup?: boolean;
// Remaining attributes forwarded to the underlying HTML <button>.
[htmlAttrs: string]: any;
}
@@ -66,6 +70,7 @@
disabled = false,
rightIcon,
className,
+ dismissPopup = false,
...htmlAttrs
} = attrs;
@@ -75,6 +80,7 @@
compact && 'pf-compact',
minimal && 'pf-minimal',
(icon && !label) && 'pf-icon-only',
+ dismissPopup && Popup.DISMISS_POPUP_GROUP_CLASS,
className,
);
diff --git a/ui/src/frontend/widgets/duration.ts b/ui/src/frontend/widgets/duration.ts
index 6f36c95..cd18e02 100644
--- a/ui/src/frontend/widgets/duration.ts
+++ b/ui/src/frontend/widgets/duration.ts
@@ -14,14 +14,14 @@
import m from 'mithril';
-import {fromNs, timeToCode} from '../../common/time';
+import {TPDuration, tpTimeToCode} from '../../common/time';
interface DurationAttrs {
- dur: number;
+ dur: TPDuration;
}
export class Duration implements m.ClassComponent<DurationAttrs> {
view(vnode: m.Vnode<DurationAttrs>) {
- return timeToCode(fromNs(vnode.attrs.dur));
+ return tpTimeToCode(vnode.attrs.dur);
}
}
diff --git a/ui/src/frontend/widgets/menu.ts b/ui/src/frontend/widgets/menu.ts
index 582e6fb..b521dab 100644
--- a/ui/src/frontend/widgets/menu.ts
+++ b/ui/src/frontend/widgets/menu.ts
@@ -68,6 +68,7 @@
...rest,
}),
showArrow: false,
+ createNewGroup: false,
},
children,
);
@@ -86,7 +87,7 @@
const classes = classNames(
active && 'pf-active',
- !disabled && closePopupOnClick && 'pf-close-parent-popup-on-click',
+ !disabled && closePopupOnClick && Popup.DISMISS_POPUP_GROUP_CLASS,
);
return m(
@@ -131,6 +132,14 @@
// Whether we should show the little arrow pointing to the trigger.
// Defaults to true.
showArrow?: boolean;
+ // Whether this popup should form a new popup group.
+ // When nesting popups, grouping controls how popups are closed.
+ // When closing popups via the Escape key, each group is closed one by one,
+ // starting at the topmost group in the stack.
+ // When using a magic button to close groups (see DISMISS_POPUP_GROUP_CLASS),
+ // only the group in which the button lives and it's children will be closed.
+ // Defaults to true.
+ createNewGroup?: boolean;
}
// A combination of a Popup and a Menu component.
@@ -146,7 +155,6 @@
{
trigger,
position: popupPosition,
- closeOnContentClick: true,
...popupAttrs,
},
m(Menu, children));
diff --git a/ui/src/frontend/widgets/popup.ts b/ui/src/frontend/widgets/popup.ts
index ca6feb8..b258a11 100644
--- a/ui/src/frontend/widgets/popup.ts
+++ b/ui/src/frontend/widgets/popup.ts
@@ -65,14 +65,19 @@
isOpen?: boolean;
// Called when the popup isOpen state should be changed in controlled mode.
onChange?: OnChangeCallback;
- // Close the popup if clicked on.
- // Defaults to false.
- closeOnContentClick?: boolean;
// Space delimited class names applied to the popup div.
className?: string;
// Whether to show a little arrow pointing to our trigger element.
// Defaults to true.
showArrow?: boolean;
+ // Whether this popup should form a new popup group.
+ // When nesting popups, grouping controls how popups are closed.
+ // When closing popups via the Escape key, each group is closed one by one,
+ // starting at the topmost group in the stack.
+ // When using a magic button to close groups (see DISMISS_POPUP_GROUP_CLASS),
+ // only the group in which the button lives and it's children will be closed.
+ // Defaults to true.
+ createNewGroup?: boolean;
}
// A popup is a portal whose position is dynamically updated so that it floats
@@ -90,6 +95,10 @@
private static readonly TRIGGER_REF = 'trigger';
private static readonly POPUP_REF = 'popup';
+ static readonly POPUP_GROUP_CLASS = 'pf-popup-group';
+
+ // Any element with this class will close its containing popup group on click
+ static readonly DISMISS_POPUP_GROUP_CLASS = 'pf-dismiss-popup-group';
view({attrs, children}: m.CVnode<PopupAttrs>): m.Children {
const {
@@ -127,6 +136,7 @@
const {
className,
showArrow = true,
+ createNewGroup = true,
} = attrs;
const portalAttrs: PortalAttrs = {
@@ -168,7 +178,8 @@
portalAttrs,
m('.pf-popup',
{
- class: classNames(className),
+ class: classNames(
+ className, createNewGroup && Popup.POPUP_GROUP_CLASS),
ref: Popup.POPUP_REF,
},
showArrow && m('.pf-popup-arrow[data-popper-arrow]'),
@@ -236,14 +247,29 @@
};
private handleDocKeyPress = (e: KeyboardEvent) => {
- if (this.closeOnEscape && e.key === 'Escape') {
- this.closePopup();
+ // Close on escape keypress if we are in the toplevel group
+ const nextGroupElement =
+ this.popupElement?.querySelector(`.${Popup.POPUP_GROUP_CLASS}`);
+ if (!nextGroupElement) {
+ if (this.closeOnEscape && e.key === 'Escape') {
+ this.closePopup();
+ }
}
};
private handleContentClick = (e: Event) => {
+ // Close the popup if the clicked element:
+ // - Is in the same group as this class
+ // - Has the magic class
const target = e.target as HTMLElement;
- if (target.closest('.pf-close-parent-popup-on-click')) {
+ const childPopup =
+ this.popupElement?.querySelector(`.${Popup.POPUP_GROUP_CLASS}`);
+ if (childPopup) {
+ if (childPopup.contains(target)) {
+ return;
+ }
+ }
+ if (target.closest(`.${Popup.DISMISS_POPUP_GROUP_CLASS}`)) {
this.closePopup();
}
};
diff --git a/ui/src/frontend/widgets/timestamp.ts b/ui/src/frontend/widgets/timestamp.ts
index 4552275..d8cc841 100644
--- a/ui/src/frontend/widgets/timestamp.ts
+++ b/ui/src/frontend/widgets/timestamp.ts
@@ -14,7 +14,7 @@
import m from 'mithril';
-import {timeToCode} from '../../common/time';
+import {tpTimeToCode} from '../../common/time';
import {toTraceTime, TPTimestamp} from '../sql_types';
interface TimestampAttrs {
@@ -23,6 +23,6 @@
export class Timestamp implements m.ClassComponent<TimestampAttrs> {
view(vnode: m.Vnode<TimestampAttrs>) {
- return timeToCode(toTraceTime(vnode.attrs.ts));
+ return tpTimeToCode(toTraceTime(vnode.attrs.ts));
}
}
diff --git a/ui/src/frontend/widgets/tree.ts b/ui/src/frontend/widgets/tree.ts
index 0428a48..e797343 100644
--- a/ui/src/frontend/widgets/tree.ts
+++ b/ui/src/frontend/widgets/tree.ts
@@ -1,7 +1,10 @@
import m from 'mithril';
+
import {classNames} from '../classnames';
import {globals} from '../globals';
+
import {Button} from './button';
+import {Spinner} from './spinner';
import {hasChildren} from './utils';
export enum TreeLayout {
@@ -48,12 +51,16 @@
}
interface TreeNodeAttrs {
- // Content to display on the left hand column.
+ // Content to display in the left hand column.
// If omitted, this side will be blank.
- left?: m.Child;
- // Content to display on the right hand column.
+ left?: m.Children;
+ // Content to display in the right hand column.
// If omitted, this side will be left blank.
- right?: m.Child;
+ right?: m.Children;
+ // Content to display in the right hand column when the node is collapsed.
+ // If omitted, the value of `right` shall be shown when collapsed instead.
+ // If the node has no children, this value is never shown.
+ summary?: m.Children;
// Whether this node is collapsed or not.
// If omitted, collapsed state 'uncontrolled' - i.e. controlled internally.
collapsed?: boolean;
@@ -86,8 +93,13 @@
);
}
- private renderRight({attrs: {right}}: m.CVnode<TreeNodeAttrs>) {
- return m('.pf-tree-right', right);
+ private renderRight(vnode: m.CVnode<TreeNodeAttrs>) {
+ const {attrs: {right, summary}} = vnode;
+ if (hasChildren(vnode) && this.isCollapsed(vnode)) {
+ return m('.pf-tree-right', summary ?? right);
+ } else {
+ return m('.pf-tree-right', right);
+ }
}
private renderChildren(vnode: m.CVnode<TreeNodeAttrs>) {
@@ -126,3 +138,81 @@
return collapsed;
}
}
+
+export function dictToTree(dict: {[key: string]: m.Child}): m.Children {
+ const children: m.Child[] = [];
+ for (const key of Object.keys(dict)) {
+ children.push(m(TreeNode, {
+ left: key,
+ right: dict[key],
+ }));
+ }
+ return m(Tree, children);
+}
+
+interface LazyTreeNodeAttrs {
+ // Same as TreeNode (see above).
+ left?: m.Children;
+ // Same as TreeNode (see above).
+ right?: m.Children;
+ // Same as TreeNode (see above).
+ summary?: m.Children;
+ // A callback to be called when the TreeNode is expanded, in order to fetch
+ // child nodes.
+ // The callback must return a promise to a function which returns m.Children.
+ // The reason the promise must return a function rather than the actual
+ // children is to avoid storing vnodes between render cycles, which is a bug
+ // in Mithril.
+ fetchData: () => Promise<() => m.Children>;
+ // Whether to keep child nodes in memory after the node has been collapsed.
+ // Defaults to true
+ hoardData?: boolean;
+}
+
+// This component is a TreeNode which only loads child nodes when it's expanded.
+// This allows us to represent huge trees without having to load all the data
+// up front, and even allows us to represent infinite or recursive trees.
+export class LazyTreeNode implements m.ClassComponent<LazyTreeNodeAttrs> {
+ private collapsed: boolean = true;
+ private renderChildren = this.renderSpinner;
+
+ private renderSpinner(): m.Children {
+ return m(TreeNode, {left: m(Spinner)});
+ }
+
+ view({attrs}: m.CVnode<LazyTreeNodeAttrs>): m.Children {
+ const {
+ left,
+ right,
+ summary,
+ fetchData,
+ hoardData = true,
+ } = attrs;
+
+ return m(
+ TreeNode,
+ {
+ left,
+ right,
+ summary,
+ collapsed: this.collapsed,
+ onCollapseChanged: (collapsed) => {
+ if (collapsed) {
+ if (!hoardData) {
+ this.renderChildren = this.renderSpinner;
+ }
+ } else {
+ fetchData().then((result) => {
+ if (!this.collapsed) {
+ this.renderChildren = result;
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ });
+ }
+ this.collapsed = collapsed;
+ globals.rafScheduler.scheduleFullRedraw();
+ },
+ },
+ this.renderChildren());
+ }
+}
diff --git a/ui/src/frontend/widgets_page.ts b/ui/src/frontend/widgets_page.ts
index 8b7b2e3..989be89 100644
--- a/ui/src/frontend/widgets_page.ts
+++ b/ui/src/frontend/widgets_page.ts
@@ -34,7 +34,7 @@
import {Spinner} from './widgets/spinner';
import {Switch} from './widgets/switch';
import {TextInput} from './widgets/text_input';
-import {Tree, TreeLayout, TreeNode} from './widgets/tree';
+import {LazyTreeNode, Tree, TreeLayout, TreeNode} from './widgets/tree';
const options: {[key: string]: boolean} = {
foobar: false,
@@ -243,6 +243,18 @@
}
}
+function recursiveLazyTreeNode(
+ left: string, summary: string, hoardData: boolean): m.Children {
+ return m(LazyTreeNode, {
+ left,
+ summary,
+ hoardData,
+ fetchData: async () => {
+ await new Promise((r) => setTimeout(r, 200));
+ return () => recursiveLazyTreeNode(left, summary, hoardData);
+ },
+ });
+}
export const WidgetsPage = createPage({
view() {
@@ -563,9 +575,14 @@
left: 'Process',
right: m(Anchor, {text: '/bin/foo[789]', icon: 'open_in_new'}),
}),
+ recursiveLazyTreeNode('Lazy', '(hoarding)', true),
+ recursiveLazyTreeNode('Lazy', '(non-hoarding)', false),
m(
TreeNode,
- {left: 'Args', right: 'foo: bar, baz: qux'},
+ {
+ left: 'Args',
+ summary: 'foo: string, baz: string, quux: string[4]',
+ },
m(TreeNode, {left: 'foo', right: 'bar'}),
m(TreeNode, {left: 'baz', right: 'qux'}),
m(
@@ -604,6 +621,27 @@
m(Button, {label: 'Cancel', minimal: true}),
)),
}),
+ m('h2', 'Nested Popups'),
+ m(
+ WidgetShowcase, {
+ renderWidget: () => m(
+ Popup,
+ {
+ trigger: m(Button, {label: 'Open the popup'}),
+ },
+ m(PopupMenu2,
+ {
+ trigger: m(Button, {label: 'Select an option'}),
+ },
+ m(MenuItem, {label: 'Option 1'}),
+ m(MenuItem, {label: 'Option 2'}),
+ ),
+ m(Button, {
+ label: 'Done',
+ dismissPopup: true,
+ }),
+ ),
+ }),
);
},
});
diff --git a/ui/src/traceconv/index.ts b/ui/src/traceconv/index.ts
index 714666a..df3e8a0 100644
--- a/ui/src/traceconv/index.ts
+++ b/ui/src/traceconv/index.ts
@@ -18,6 +18,7 @@
ConversionJobName,
ConversionJobStatus,
} from '../common/conversion_jobs';
+import {TPTime} from '../common/time';
import traceconv from '../gen/traceconv';
const selfWorker = self as {} as Worker;
@@ -176,7 +177,7 @@
kind: 'ConvertTraceToPprof';
trace: Blob;
pid: number;
- ts: number;
+ ts: TPTime;
}
function isConvertTraceToPprof(msg: Args): msg is ConvertTraceToPprofArgs {
@@ -186,8 +187,7 @@
return true;
}
-async function ConvertTraceToPprof(
-trace: Blob, pid: number, ts: number) {
+async function ConvertTraceToPprof(trace: Blob, pid: number, ts: TPTime) {
const jobName = 'convert_pprof';
updateJobStatus(jobName, ConversionJobStatus.InProgress);
const args = [
diff --git a/ui/src/tracks/actual_frames/index.ts b/ui/src/tracks/actual_frames/index.ts
index 927dea4..7f5afb0 100644
--- a/ui/src/tracks/actual_frames/index.ts
+++ b/ui/src/tracks/actual_frames/index.ts
@@ -14,7 +14,7 @@
import {PluginContext} from '../../common/plugin_api';
import {NUM, NUM_NULL, STR} from '../../common/query_result';
-import {fromNs, toNs} from '../../common/time';
+import {fromNs, TPDuration, TPTime, tpTimeToNanos} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {TrackController} from '../../controller/track_controller';
import {NewTrackArgs, Track} from '../../frontend/track';
@@ -51,16 +51,17 @@
static readonly kind = ACTUAL_FRAMES_SLICE_TRACK_KIND;
private maxDurNs = 0;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
- const startNs = toNs(start);
- const endNs = toNs(end);
+ const startNs = tpTimeToNanos(start);
+ const endNs = tpTimeToNanos(end);
const pxSize = this.pxSize();
// ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
// be an even number, so we can snap in the middle.
- const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
+ const bucketNs =
+ Math.max(Math.round(Number(resolution) * pxSize / 2) * 2, 1);
if (this.maxDurNs === 0) {
const maxDurResult = await this.query(`
diff --git a/ui/src/tracks/android_log/index.ts b/ui/src/tracks/android_log/index.ts
index b2a824b..6c8a1bc 100644
--- a/ui/src/tracks/android_log/index.ts
+++ b/ui/src/tracks/android_log/index.ts
@@ -14,7 +14,7 @@
import {PluginContext} from '../../common/plugin_api';
import {NUM} from '../../common/query_result';
-import {fromNs, toNsCeil, toNsFloor} from '../../common/time';
+import {fromNs, TPDuration, TPTime} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {LIMIT} from '../../common/track_data';
import {
@@ -61,21 +61,15 @@
class AndroidLogTrackController extends TrackController<Config, Data> {
static readonly kind = ANDROID_LOGS_TRACK_KIND;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
- const startNs = toNsFloor(start);
- const endNs = toNsCeil(end);
-
- // |resolution| is in s/px the frontend wants.
- const quantNs = toNsCeil(resolution);
-
const queryRes = await this.query(`
select
- cast(ts / ${quantNs} as integer) * ${quantNs} as tsQuant,
+ cast(ts / ${resolution} as integer) * ${resolution} as tsQuant,
prio,
count(prio) as numEvents
from android_logs
- where ts >= ${startNs} and ts <= ${endNs}
+ where ts >= ${start} and ts <= ${end}
group by tsQuant, prio
order by tsQuant, prio limit ${LIMIT};`);
@@ -113,16 +107,16 @@
}
renderCanvas(ctx: CanvasRenderingContext2D): void {
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {visibleTimeScale, windowSpan} = globals.frontendLocalState;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
- const dataStartPx = timeScale.timeToPx(data.start);
- const dataEndPx = timeScale.timeToPx(data.end);
- const visibleStartPx = timeScale.timeToPx(visibleWindowTime.start);
- const visibleEndPx = timeScale.timeToPx(visibleWindowTime.end);
+ const dataStartPx = visibleTimeScale.tpTimeToPx(data.start);
+ const dataEndPx = visibleTimeScale.tpTimeToPx(data.end);
+ const visibleStartPx = windowSpan.start;
+ const visibleEndPx = windowSpan.end;
checkerboardExcept(
ctx,
@@ -133,7 +127,7 @@
dataEndPx);
const quantWidth =
- Math.max(EVT_PX, timeScale.deltaTimeToPx(data.resolution));
+ Math.max(EVT_PX, visibleTimeScale.durationToPx(data.resolution));
const blockH = RECT_HEIGHT / LEVELS.length;
for (let i = 0; i < data.timestamps.length; i++) {
for (let lev = 0; lev < LEVELS.length; lev++) {
@@ -143,7 +137,7 @@
}
if (!hasEventsForCurColor) continue;
ctx.fillStyle = LEVELS[lev].color;
- const px = Math.floor(timeScale.timeToPx(data.timestamps[i]));
+ const px = Math.floor(visibleTimeScale.secondsToPx(data.timestamps[i]));
ctx.fillRect(px, MARGIN_TOP + blockH * lev, quantWidth, blockH);
} // for(lev)
} // for (timestamps)
diff --git a/ui/src/tracks/async_slices/index.ts b/ui/src/tracks/async_slices/index.ts
index 338e02a..997577f 100644
--- a/ui/src/tracks/async_slices/index.ts
+++ b/ui/src/tracks/async_slices/index.ts
@@ -13,8 +13,8 @@
// limitations under the License.
import {PluginContext} from '../../common/plugin_api';
-import {NUM, NUM_NULL, STR} from '../../common/query_result';
-import {fromNs, toNs} from '../../common/time';
+import {LONG_NULL, NUM, STR} from '../../common/query_result';
+import {fromNs, TPDuration, TPTime} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {
TrackController,
@@ -43,26 +43,24 @@
class AsyncSliceTrackController extends TrackController<Config, Data> {
static readonly kind = ASYNC_SLICE_TRACK_KIND;
- private maxDurNs = 0;
+ private maxDurNs: TPDuration = 0n;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
- const startNs = toNs(start);
- const endNs = toNs(end);
-
const pxSize = this.pxSize();
// ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
// be an even number, so we can snap in the middle.
- const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
+ const bucketNs =
+ Math.max(Math.round(Number(resolution) * pxSize / 2) * 2, 1);
- if (this.maxDurNs === 0) {
+ if (this.maxDurNs === 0n) {
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(',')}'
`);
- this.maxDurNs = maxDurResult.firstRow({maxDur: NUM_NULL}).maxDur || 0;
+ this.maxDurNs = maxDurResult.firstRow({maxDur: LONG_NULL}).maxDur || 0n;
}
const queryRes = await this.query(`
@@ -78,8 +76,8 @@
from experimental_slice_layout
where
filter_track_ids = '${this.config.trackIds.join(',')}' and
- ts >= ${startNs - this.maxDurNs} and
- ts <= ${endNs}
+ ts >= ${start - this.maxDurNs} and
+ ts <= ${end}
group by tsq, layout_depth
order by tsq, layout_depth
`);
diff --git a/ui/src/tracks/chrome_slices/index.ts b/ui/src/tracks/chrome_slices/index.ts
index 23f9a5e..4e70507 100644
--- a/ui/src/tracks/chrome_slices/index.ts
+++ b/ui/src/tracks/chrome_slices/index.ts
@@ -15,9 +15,16 @@
import {Actions} from '../../common/actions';
import {cropText, drawIncompleteSlice} from '../../common/canvas_utils';
import {colorForThreadIdleSlice, hslForSlice} from '../../common/colorizer';
+import {
+ HighPrecisionTime,
+} from '../../common/high_precision_time';
import {PluginContext} from '../../common/plugin_api';
-import {NUM, NUM_NULL, STR} from '../../common/query_result';
-import {fromNs, toNs} from '../../common/time';
+import {LONG_NULL, NUM, NUM_NULL, STR} from '../../common/query_result';
+import {
+ fromNs,
+ TPDuration,
+ TPTime,
+} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {
TrackController,
@@ -60,27 +67,25 @@
export class ChromeSliceTrackController extends TrackController<Config, Data> {
static kind = SLICE_TRACK_KIND;
- private maxDurNs = 0;
+ private maxDurNs: TPDuration = 0n;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
- const startNs = toNs(start);
- const endNs = toNs(end);
-
const pxSize = this.pxSize();
// ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
// be an even number, so we can snap in the middle.
- const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
+ const bucketNs =
+ Math.max(Math.round(Number(resolution) * pxSize / 2) * 2, 1);
const tableName = this.namespaceTable('slice');
- if (this.maxDurNs === 0) {
+ if (this.maxDurNs === 0n) {
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.query(query);
- this.maxDurNs = queryRes.firstRow({maxDur: NUM_NULL}).maxDur || 0;
+ this.maxDurNs = queryRes.firstRow({maxDur: LONG_NULL}).maxDur || 0n;
}
// Buckets are always even and positive, don't quantize once we zoom to
@@ -103,8 +108,8 @@
thread_dur as threadDur
FROM ${tableName}
WHERE track_id = ${this.config.trackId} AND
- ts >= (${startNs - this.maxDurNs}) AND
- ts <= ${endNs}
+ ts >= (${start - this.maxDurNs}) AND
+ ts <= ${end}
GROUP BY depth, tsq`;
const queryRes = await this.query(query);
@@ -209,7 +214,7 @@
renderCanvas(ctx: CanvasRenderingContext2D): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {visibleTimeScale, visibleWindowTime} = globals.frontendLocalState;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
@@ -219,10 +224,10 @@
checkerboardExcept(
ctx,
this.getHeight(),
- timeScale.timeToPx(visibleWindowTime.start),
- timeScale.timeToPx(visibleWindowTime.end),
- timeScale.timeToPx(data.start),
- timeScale.timeToPx(data.end),
+ visibleTimeScale.hpTimeToPx(visibleWindowTime.start),
+ visibleTimeScale.hpTimeToPx(visibleWindowTime.end),
+ visibleTimeScale.tpTimeToPx(data.start),
+ visibleTimeScale.tpTimeToPx(data.end),
);
ctx.textAlign = 'center';
@@ -245,7 +250,7 @@
const title = data.strings[titleId];
const colorOverride = data.colors && data.strings[data.colors[i]];
if (isIncomplete) { // incomplete slice
- tEnd = visibleWindowTime.end;
+ tEnd = visibleWindowTime.end.seconds;
}
const rect = this.getSliceRect(tStart, tEnd, depth);
@@ -369,10 +374,14 @@
getSliceIndex({x, y}: {x: number, y: number}): number|void {
const data = this.data();
if (data === undefined) return;
- const {timeScale} = globals.frontendLocalState;
+ const {
+ visibleTimeScale: timeScale,
+ visibleWindowTime,
+ } = globals.frontendLocalState;
if (y < TRACK_PADDING) return;
- const instantWidthTime = timeScale.deltaPxToDuration(HALF_CHEVRON_WIDTH_PX);
- const t = timeScale.pxToTime(x);
+ const instantWidthTime = timeScale.pxDeltaToDuration(HALF_CHEVRON_WIDTH_PX);
+ const instantWidthTimeSec = instantWidthTime.seconds;
+ const t = timeScale.pxToHpTime(x).seconds;
const depth = Math.floor((y - TRACK_PADDING) / SLICE_HEIGHT);
for (let i = 0; i < data.starts.length; i++) {
if (depth !== data.depths[i]) {
@@ -380,13 +389,13 @@
}
const tStart = data.starts[i];
if (data.isInstant[i]) {
- if (Math.abs(tStart - t) < instantWidthTime) {
+ if (Math.abs(tStart - t) < instantWidthTimeSec) {
return i;
}
} else {
let tEnd = data.ends[i];
if (data.isIncomplete[i]) {
- tEnd = globals.frontendLocalState.visibleWindowTime.end;
+ tEnd = visibleWindowTime.end.seconds;
}
if (tStart <= t && t <= tEnd) {
return i;
@@ -435,17 +444,28 @@
getSliceRect(tStart: number, tEnd: number, depth: number): SliceRect
|undefined {
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
- const pxEnd = timeScale.timeToPx(visibleWindowTime.end);
- const left = Math.max(timeScale.timeToPx(tStart), 0);
- const right = Math.min(timeScale.timeToPx(tEnd), pxEnd);
+ const {
+ visibleTimeScale: timeScale,
+ visibleWindowTime,
+ windowSpan,
+ } = globals.frontendLocalState;
+
+ const pxEnd = windowSpan.end;
+ const left = Math.max(timeScale.secondsToPx(tStart), 0);
+ const right = Math.min(timeScale.secondsToPx(tEnd), pxEnd);
+
+ const visible =
+ !(visibleWindowTime.start.isGreaterThan(
+ HighPrecisionTime.fromSeconds(tEnd)) ||
+ visibleWindowTime.end.isLessThan(
+ HighPrecisionTime.fromSeconds(tStart)));
+
return {
left,
width: Math.max(right - left, 1),
top: TRACK_PADDING + depth * SLICE_HEIGHT,
height: SLICE_HEIGHT,
- visible:
- !(tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end),
+ visible,
};
}
}
diff --git a/ui/src/tracks/counter/index.ts b/ui/src/tracks/counter/index.ts
index 9aa8f74..f22e8c7 100644
--- a/ui/src/tracks/counter/index.ts
+++ b/ui/src/tracks/counter/index.ts
@@ -19,13 +19,18 @@
import {Actions} from '../../common/actions';
import {
EngineProxy,
+ LONG_NULL,
NUM,
- NUM_NULL,
PluginContext,
STR,
TrackInfo,
} from '../../common/plugin_api';
-import {fromNs, toNs} from '../../common/time';
+import {
+ fromNs,
+ TPDuration,
+ TPTime,
+ tpTimeFromSeconds,
+} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {
TrackController,
@@ -62,8 +67,8 @@
name: string;
maximumValue?: number;
minimumValue?: number;
- startTs?: number;
- endTs?: number;
+ startTs?: TPTime;
+ endTs?: TPTime;
namespace: string;
trackId: number;
scale?: CounterScaleOptions;
@@ -76,18 +81,16 @@
private minimumValueSeen = 0;
private maximumDeltaSeen = 0;
private minimumDeltaSeen = 0;
- private maxDurNs = 0;
+ private maxDurNs: TPDuration = 0n;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
- const startNs = toNs(start);
- const endNs = toNs(end);
-
const pxSize = this.pxSize();
// ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
// be an even number, so we can snap in the middle.
- const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
+ const bucketNs =
+ Math.max(Math.round(Number(resolution) * pxSize / 2) * 2, 1);
if (!this.setup) {
if (this.config.namespace === undefined) {
@@ -123,7 +126,7 @@
) as maxDur
from ${this.tableName('counter_view')}
`);
- this.maxDurNs = maxDurResult.firstRow({maxDur: NUM_NULL}).maxDur || 0;
+ this.maxDurNs = maxDurResult.firstRow({maxDur: LONG_NULL}).maxDur || 0n;
const queryRes = await this.query(`
select
@@ -151,7 +154,7 @@
value_at_max_ts(ts, id) as lastId,
value_at_max_ts(ts, value) as lastValue
from ${this.tableName('counter_view')}
- where ts >= ${startNs - this.maxDurNs} and ts <= ${endNs}
+ where ts >= ${start - this.maxDurNs} and ts <= ${end}
group by tsq
order by tsq
`);
@@ -285,7 +288,10 @@
renderCanvas(ctx: CanvasRenderingContext2D): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {
+ visibleTimeScale: timeScale,
+ windowSpan,
+ } = globals.frontendLocalState;
const data = this.data();
// Can't possibly draw anything.
@@ -321,7 +327,7 @@
minimumValue = data.minimumRate;
}
- const endPx = Math.floor(timeScale.timeToPx(visibleWindowTime.end));
+ const endPx = windowSpan.end;
const zeroY = MARGIN_TOP + RECT_HEIGHT / (minimumValue < 0 ? 2 : 1);
// Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
@@ -366,7 +372,7 @@
ctx.strokeStyle = `hsl(${hue}, 45%, 45%)`;
const calculateX = (ts: number) => {
- return Math.floor(timeScale.timeToPx(ts));
+ return Math.floor(timeScale.secondsToPx(ts));
};
const calculateY = (value: number) => {
return MARGIN_TOP + RECT_HEIGHT -
@@ -427,10 +433,10 @@
ctx.fillStyle = `hsl(${hue}, 45%, 75%)`;
ctx.strokeStyle = `hsl(${hue}, 45%, 45%)`;
- const xStart = Math.floor(timeScale.timeToPx(this.hoveredTs));
+ const xStart = Math.floor(timeScale.secondsToPx(this.hoveredTs));
const xEnd = this.hoveredTsEnd === undefined ?
endPx :
- Math.floor(timeScale.timeToPx(this.hoveredTsEnd));
+ Math.floor(timeScale.secondsToPx(this.hoveredTsEnd));
const y = MARGIN_TOP + RECT_HEIGHT -
Math.round(((this.hoveredValue - yMin) / yRange) * RECT_HEIGHT);
@@ -463,9 +469,10 @@
// TODO(hjd): Refactor this into checkerboardExcept
{
- const endPx = timeScale.timeToPx(visibleWindowTime.end);
- const counterEndPx =
- Math.min(timeScale.timeToPx(this.config.endTs || Infinity), endPx);
+ let counterEndPx = Infinity;
+ if (this.config.endTs) {
+ counterEndPx = Math.min(timeScale.tpTimeToPx(this.config.endTs), endPx);
+ }
// Grey out RHS.
if (counterEndPx < endPx) {
@@ -479,18 +486,18 @@
checkerboardExcept(
ctx,
this.getHeight(),
- timeScale.timeToPx(visibleWindowTime.start),
- timeScale.timeToPx(visibleWindowTime.end),
- timeScale.timeToPx(data.start),
- timeScale.timeToPx(data.end));
+ windowSpan.start,
+ windowSpan.end,
+ timeScale.tpTimeToPx(data.start),
+ timeScale.tpTimeToPx(data.end));
}
onMouseMove(pos: {x: number, y: number}) {
const data = this.data();
if (data === undefined) return;
this.mousePos = pos;
- const {timeScale} = globals.frontendLocalState;
- const time = timeScale.pxToTime(pos.x);
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const time = visibleTimeScale.pxToHpTime(pos.x).seconds;
const values = this.config.scale === 'DELTA_FROM_PREVIOUS' ?
data.totalDeltas :
@@ -509,8 +516,8 @@
onMouseClick({x}: {x: number}) {
const data = this.data();
if (data === undefined) return false;
- const {timeScale} = globals.frontendLocalState;
- const time = timeScale.pxToTime(x);
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const time = visibleTimeScale.pxToHpTime(x).seconds;
const [left, right] = searchSegment(data.timestamps, time);
if (left === -1) {
return false;
@@ -518,8 +525,8 @@
const counterId = data.lastIds[left];
if (counterId === -1) return true;
globals.makeSelection(Actions.selectCounter({
- leftTs: toNs(data.timestamps[left]),
- rightTs: right !== -1 ? toNs(data.timestamps[right]) : -1,
+ leftTs: tpTimeFromSeconds(data.timestamps[left]),
+ rightTs: tpTimeFromSeconds(right !== -1 ? data.timestamps[right] : -1),
id: counterId,
trackId: this.trackState.id,
}));
diff --git a/ui/src/tracks/cpu_freq/index.ts b/ui/src/tracks/cpu_freq/index.ts
index 8bb2e3b..7956172 100644
--- a/ui/src/tracks/cpu_freq/index.ts
+++ b/ui/src/tracks/cpu_freq/index.ts
@@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {BigintMath} from '../../base/bigint_math';
import {searchSegment} from '../../base/binary_search';
import {assertTrue} from '../../base/logging';
import {hueForCpu} from '../../common/colorizer';
import {PluginContext} from '../../common/plugin_api';
import {NUM, NUM_NULL, QueryResult} from '../../common/query_result';
-import {fromNs, toNs} from '../../common/time';
+import {fromNs, TPDuration, TPTime, tpTimeToNanos} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {
TrackController,
@@ -96,15 +97,17 @@
this.cachedBucketNs = bucketNs;
}
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
// The resolution should always be a power of two for the logic of this
// function to make sense.
- const resolutionNs = toNs(resolution);
- assertTrue(Math.log2(resolutionNs) % 1 === 0);
+ assertTrue(
+ BigintMath.popcount(resolution) === 1,
+ `${resolution} is not a power of 2`);
+ const resolutionNs = Number(resolution);
- const startNs = toNs(start);
- const endNs = toNs(end);
+ const startNs = tpTimeToNanos(start);
+ const endNs = tpTimeToNanos(end);
// ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
// be an even number, so we can snap in the middle.
@@ -289,7 +292,11 @@
renderCanvas(ctx: CanvasRenderingContext2D): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {
+ visibleTimeScale,
+ visibleWindowTime,
+ windowSpan,
+ } = globals.frontendLocalState;
const data = this.data();
if (data === undefined || data.timestamps.length === 0) {
@@ -302,7 +309,7 @@
assertTrue(data.timestamps.length === data.maxFreqKHz.length);
assertTrue(data.timestamps.length === data.lastIdleValues.length);
- const endPx = timeScale.timeToPx(visibleWindowTime.end);
+ const endPx = windowSpan.end;
const zeroY = MARGIN_TOP + RECT_HEIGHT;
// Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
@@ -326,17 +333,18 @@
ctx.strokeStyle = `hsl(${hue}, ${saturation}%, 55%)`;
const calculateX = (timestamp: number) => {
- return Math.floor(timeScale.timeToPx(timestamp));
+ return Math.floor(visibleTimeScale.secondsToPx(timestamp));
};
const calculateY = (value: number) => {
return zeroY - Math.round((value / yMax) * RECT_HEIGHT);
};
- const [rawStartIdx] =
- searchSegment(data.timestamps, visibleWindowTime.start);
+ const startSec = visibleWindowTime.start.seconds;
+ const endSec = visibleWindowTime.end.seconds;
+ const [rawStartIdx] = searchSegment(data.timestamps, startSec);
const startIdx = rawStartIdx === -1 ? 0 : rawStartIdx;
- const [, rawEndIdx] = searchSegment(data.timestamps, visibleWindowTime.end);
+ const [, rawEndIdx] = searchSegment(data.timestamps, endSec);
const endIdx = rawEndIdx === -1 ? data.timestamps.length : rawEndIdx;
ctx.beginPath();
@@ -383,10 +391,10 @@
// coordinates. Instead we use floating point which prevents flickering as
// we pan and zoom; this relies on the browser anti-aliasing pixels
// correctly.
- const x = timeScale.timeToPx(data.timestamps[i]);
+ const x = visibleTimeScale.secondsToPx(data.timestamps[i]);
const xEnd = i === data.lastIdleValues.length - 1 ?
finalX :
- timeScale.timeToPx(data.timestamps[i + 1]);
+ visibleTimeScale.secondsToPx(data.timestamps[i + 1]);
const width = xEnd - x;
const height = calculateY(data.lastFreqKHz[i]) - zeroY;
@@ -402,10 +410,10 @@
ctx.fillStyle = `hsl(${hue}, 45%, 75%)`;
ctx.strokeStyle = `hsl(${hue}, 45%, 45%)`;
- const xStart = Math.floor(timeScale.timeToPx(this.hoveredTs));
+ const xStart = Math.floor(visibleTimeScale.secondsToPx(this.hoveredTs));
const xEnd = this.hoveredTsEnd === undefined ?
endPx :
- Math.floor(timeScale.timeToPx(this.hoveredTsEnd));
+ Math.floor(visibleTimeScale.secondsToPx(this.hoveredTsEnd));
const y = zeroY - Math.round((this.hoveredValue / yMax) * RECT_HEIGHT);
// Highlight line.
@@ -446,18 +454,18 @@
checkerboardExcept(
ctx,
this.getHeight(),
- timeScale.timeToPx(visibleWindowTime.start),
- timeScale.timeToPx(visibleWindowTime.end),
- timeScale.timeToPx(data.start),
- timeScale.timeToPx(data.end));
+ windowSpan.start,
+ windowSpan.end,
+ visibleTimeScale.tpTimeToPx(data.start),
+ visibleTimeScale.tpTimeToPx(data.end));
}
onMouseMove(pos: {x: number, y: number}) {
const data = this.data();
if (data === undefined) return;
this.mousePos = pos;
- const {timeScale} = globals.frontendLocalState;
- const time = timeScale.pxToTime(pos.x);
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const time = visibleTimeScale.pxToHpTime(pos.x).seconds;
const [left, right] = searchSegment(data.timestamps, time);
this.hoveredTs = left === -1 ? undefined : data.timestamps[left];
diff --git a/ui/src/tracks/cpu_profile/index.ts b/ui/src/tracks/cpu_profile/index.ts
index eee7b17..028d5b1 100644
--- a/ui/src/tracks/cpu_profile/index.ts
+++ b/ui/src/tracks/cpu_profile/index.ts
@@ -18,7 +18,7 @@
import {hslForSlice} from '../../common/colorizer';
import {PluginContext} from '../../common/plugin_api';
import {NUM} from '../../common/query_result';
-import {fromNs, toNs} from '../../common/time';
+import {fromNs, TPDuration, TPTime} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {
TrackController,
@@ -46,7 +46,7 @@
class CpuProfileTrackController extends TrackController<Config, Data> {
static readonly kind = CPU_PROFILE_TRACK_KIND;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
const query = `select
id,
@@ -105,7 +105,7 @@
renderCanvas(ctx: CanvasRenderingContext2D): void {
const {
- timeScale,
+ visibleTimeScale: timeScale,
} = globals.frontendLocalState;
const data = this.data();
@@ -120,7 +120,7 @@
const strokeWidth = isSelected ? 3 : 0;
this.drawMarker(
ctx,
- timeScale.timeToPx(fromNs(centerX)),
+ timeScale.secondsToPx(fromNs(centerX)),
this.centerY,
isHovered,
strokeWidth,
@@ -146,8 +146,8 @@
if (clusterStartIndex !== clusterEndIndex) {
const startX = data.tsStarts[clusterStartIndex];
const endX = data.tsStarts[clusterEndIndex];
- const leftPx = timeScale.timeToPx(fromNs(startX)) - this.markerWidth;
- const rightPx = timeScale.timeToPx(fromNs(endX)) + this.markerWidth;
+ const leftPx = timeScale.secondsToPx(fromNs(startX)) - this.markerWidth;
+ const rightPx = timeScale.secondsToPx(fromNs(endX)) + this.markerWidth;
const width = rightPx - leftPx;
ctx.fillStyle = colorForSample(callsiteId, false);
ctx.fillRect(leftPx, MARGIN_TOP, width, BAR_HEIGHT);
@@ -179,8 +179,10 @@
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 {
+ visibleTimeScale: timeScale,
+ } = globals.frontendLocalState;
+ const time = timeScale.pxToHpTime(x).nanos;
const [left, right] = searchSegment(data.tsStarts, time);
const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
this.hoveredTs = index === -1 ? undefined : data.tsStarts[index];
@@ -193,9 +195,11 @@
onMouseClick({x, y}: {x: number, y: number}) {
const data = this.data();
if (data === undefined) return false;
- const {timeScale} = globals.frontendLocalState;
+ const {
+ visibleTimeScale: timeScale,
+ } = globals.frontendLocalState;
- const time = toNs(timeScale.pxToTime(x));
+ const time = timeScale.pxToHpTime(x).nanos;
const [left, right] = searchSegment(data.tsStarts, time);
const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
@@ -217,13 +221,13 @@
right: number): number {
let index = -1;
if (left !== -1) {
- const centerX = timeScale.timeToPx(fromNs(data.tsStarts[left]));
+ const centerX = timeScale.secondsToPx(fromNs(data.tsStarts[left]));
if (this.isInMarker(x, y, centerX)) {
index = left;
}
}
if (right !== -1) {
- const centerX = timeScale.timeToPx(fromNs(data.tsStarts[right]));
+ const centerX = timeScale.secondsToPx(fromNs(data.tsStarts[right]));
if (this.isInMarker(x, y, centerX)) {
index = right;
}
diff --git a/ui/src/tracks/cpu_slices/index.ts b/ui/src/tracks/cpu_slices/index.ts
index 0953d2f..4264069 100644
--- a/ui/src/tracks/cpu_slices/index.ts
+++ b/ui/src/tracks/cpu_slices/index.ts
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {BigintMath} from '../../base/bigint_math';
import {search, searchEq, searchSegment} from '../../base/binary_search';
import {assertTrue} from '../../base/logging';
import {Actions} from '../../common/actions';
@@ -23,7 +24,15 @@
import {colorForThread} from '../../common/colorizer';
import {PluginContext} from '../../common/plugin_api';
import {NUM} from '../../common/query_result';
-import {fromNs, timeToString, toNs} from '../../common/time';
+import {
+ fromNs,
+ toNs,
+ TPDuration,
+ TPTime,
+ tpTimeFromSeconds,
+ tpTimeToNanos,
+ tpTimeToString,
+} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {
TrackController,
@@ -102,16 +111,19 @@
this.cachedBucketNs = bucketNs;
}
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
- const resolutionNs = toNs(resolution);
+ assertTrue(
+ BigintMath.popcount(resolution) === 1,
+ `${resolution} is not a power of 2`);
+ const resolutionNs = Number(resolution);
// The resolution should always be a power of two for the logic of this
// function to make sense.
assertTrue(Math.log2(resolutionNs) % 1 === 0);
- const boundStartNs = toNs(start);
- const boundEndNs = toNs(end);
+ const boundStartNs = tpTimeToNanos(start);
+ const boundEndNs = tpTimeToNanos(end);
// ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
// be an even number, so we can snap in the middle.
@@ -223,7 +235,7 @@
renderCanvas(ctx: CanvasRenderingContext2D): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {visibleTimeScale, windowSpan} = globals.frontendLocalState;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
@@ -233,28 +245,35 @@
checkerboardExcept(
ctx,
this.getHeight(),
- timeScale.timeToPx(visibleWindowTime.start),
- timeScale.timeToPx(visibleWindowTime.end),
- timeScale.timeToPx(data.start),
- timeScale.timeToPx(data.end));
+ windowSpan.start,
+ windowSpan.end,
+ visibleTimeScale.tpTimeToPx(data.start),
+ visibleTimeScale.tpTimeToPx(data.end));
this.renderSlices(ctx, data);
}
renderSlices(ctx: CanvasRenderingContext2D, data: Data): void {
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {
+ visibleTimeScale,
+ visibleWindowTime,
+ } = globals.frontendLocalState;
assertTrue(data.starts.length === data.ends.length);
assertTrue(data.starts.length === data.utids.length);
+ const visWindowEndPx = visibleTimeScale.hpTimeToPx(visibleWindowTime.end);
+
ctx.textAlign = 'center';
ctx.font = '12px Roboto Condensed';
const charWidth = ctx.measureText('dbpqaouk').width / 8;
- const rawStartIdx =
- data.ends.findIndex((end) => end >= visibleWindowTime.start);
+ const startSec = visibleWindowTime.start.seconds;
+ const endSec = visibleWindowTime.end.seconds;
+
+ const rawStartIdx = data.ends.findIndex((end) => end >= startSec);
const startIdx = rawStartIdx === -1 ? 0 : rawStartIdx;
- const [, rawEndIdx] = searchSegment(data.starts, visibleWindowTime.end);
+ const [, rawEndIdx] = searchSegment(data.starts, endSec);
const endIdx = rawEndIdx === -1 ? data.starts.length : rawEndIdx;
for (let i = startIdx; i < endIdx; i++) {
@@ -266,10 +285,10 @@
// window, else it might spill over the window and the end would not be
// visible as a zigzag line.
if (data.ids[i] === data.lastRowId && data.isIncomplete[i]) {
- tEnd = visibleWindowTime.end;
+ tEnd = visibleWindowTime.end.seconds;
}
- const rectStart = timeScale.timeToPx(tStart);
- const rectEnd = timeScale.timeToPx(tEnd);
+ const rectStart = visibleTimeScale.secondsToPx(tStart);
+ const rectEnd = visibleTimeScale.secondsToPx(tEnd);
const rectWidth = Math.max(1, rectEnd - rectStart);
const threadInfo = globals.threads.get(utid);
@@ -317,8 +336,7 @@
title = `${threadInfo.threadName} [${threadInfo.tid}]`;
}
}
- const right =
- Math.min(timeScale.timeToPx(visibleWindowTime.end), rectEnd);
+ const right = Math.min(visWindowEndPx, rectEnd);
const left = Math.max(rectStart, 0);
const visibleWidth = Math.max(right - left, 1);
title = cropText(title, charWidth, visibleWidth);
@@ -341,8 +359,8 @@
const tEnd = data.ends[startIndex];
const utid = data.utids[startIndex];
const color = colorForThread(globals.threads.get(utid));
- const rectStart = timeScale.timeToPx(tStart);
- const rectEnd = timeScale.timeToPx(tEnd);
+ const rectStart = visibleTimeScale.secondsToPx(tStart);
+ const rectEnd = visibleTimeScale.secondsToPx(tEnd);
const rectWidth = Math.max(1, rectEnd - rectStart);
// Draw a rectangle around the slice that is currently selected.
@@ -353,7 +371,7 @@
ctx.closePath();
// Draw arrow from wakeup time of current slice.
if (details.wakeupTs) {
- const wakeupPos = timeScale.timeToPx(details.wakeupTs);
+ const wakeupPos = visibleTimeScale.tpTimeToPx(details.wakeupTs);
const latencyWidth = rectStart - wakeupPos;
drawDoubleHeadedArrow(
ctx,
@@ -362,7 +380,8 @@
latencyWidth,
latencyWidth >= 20);
// Latency time with a white semi-transparent background.
- const displayText = timeToString(tStart - details.wakeupTs);
+ const latency = tpTimeFromSeconds(tStart) - details.wakeupTs;
+ const displayText = tpTimeToString(latency);
const measured = ctx.measureText(displayText);
if (latencyWidth >= measured.width + 2) {
ctx.fillStyle = 'rgba(255,255,255,0.7)';
@@ -383,7 +402,8 @@
// Draw diamond if the track being drawn is the cpu of the waker.
if (this.config.cpu === details.wakerCpu && details.wakeupTs) {
- const wakeupPos = Math.floor(timeScale.timeToPx(details.wakeupTs));
+ const wakeupPos =
+ Math.floor(visibleTimeScale.tpTimeToPx(details.wakeupTs));
ctx.beginPath();
ctx.moveTo(wakeupPos, MARGIN_TOP + RECT_HEIGHT / 2 + 8);
ctx.fillStyle = 'black';
@@ -411,13 +431,13 @@
const data = this.data();
this.mousePos = pos;
if (data === undefined) return;
- const {timeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.frontendLocalState;
if (pos.y < MARGIN_TOP || pos.y > MARGIN_TOP + RECT_HEIGHT) {
this.utidHoveredInThisTrack = -1;
globals.dispatch(Actions.setHoveredUtidAndPid({utid: -1, pid: -1}));
return;
}
- const t = timeScale.pxToTime(pos.x);
+ const t = visibleTimeScale.pxToHpTime(pos.x).seconds;
let hoveredUtid = -1;
for (let i = 0; i < data.starts.length; i++) {
@@ -445,8 +465,8 @@
onMouseClick({x}: {x: number}) {
const data = this.data();
if (data === undefined) return false;
- const {timeScale} = globals.frontendLocalState;
- const time = timeScale.pxToTime(x);
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const time = visibleTimeScale.pxToHpTime(x).seconds;
const index = search(data.starts, time);
const id = index === -1 ? undefined : data.ids[index];
if (!id || this.utidHoveredInThisTrack === -1) return false;
diff --git a/ui/src/tracks/debug/add_debug_track_menu.ts b/ui/src/tracks/debug/add_debug_track_menu.ts
index 2982773..32bc871 100644
--- a/ui/src/tracks/debug/add_debug_track_menu.ts
+++ b/ui/src/tracks/debug/add_debug_track_menu.ts
@@ -89,7 +89,7 @@
m(FormLabel,
{for: 'track_name',
},
- 'Name'),
+ 'Track name'),
m(TextInput, {
id: 'track_name',
onkeydown: (e: KeyboardEvent) => {
@@ -109,7 +109,7 @@
FormButtonBar,
m(Button, {
label: 'Show',
- className: 'pf-close-parent-popup-on-click',
+ dismissPopup: true,
onclick: (e: Event) => {
e.preventDefault();
addDebugTrack(
diff --git a/ui/src/tracks/debug/details_tab.ts b/ui/src/tracks/debug/details_tab.ts
index c168eb6..50c2319 100644
--- a/ui/src/tracks/debug/details_tab.ts
+++ b/ui/src/tracks/debug/details_tab.ts
@@ -15,19 +15,21 @@
import m from 'mithril';
import {ColumnType} from '../../common/query_result';
+import {tpDurationFromSql, tpTimeFromSql} from '../../common/time';
import {
BottomTab,
bottomTabRegistry,
NewBottomTabArgs,
} from '../../frontend/bottom_tab';
import {globals} from '../../frontend/globals';
-import {timestampFromSqlNanos} from '../../frontend/sql_types';
+import {asTPTimestamp} from '../../frontend/sql_types';
import {Duration} from '../../frontend/widgets/duration';
import {Timestamp} from '../../frontend/widgets/timestamp';
-import {Tree, TreeNode} from '../../frontend/widgets/tree';
+import {dictToTree} from '../../frontend/widgets/tree';
+
import {ARG_PREFIX} from './add_debug_track_menu';
-interface DebugSliceDetalsTabConfig {
+interface DebugSliceDetailsTabConfig {
sqlTableName: string;
id: number;
}
@@ -42,18 +44,8 @@
return val.toString();
}
-function dictToTree(dict: {[key: string]: m.Child}): m.Children {
- const children: m.Child[] = [];
- for (const key of Object.keys(dict)) {
- children.push(m(TreeNode, {
- left: key,
- right: dict[key],
- }));
- }
- return m(Tree, children);
-}
-
-export class DebugSliceDetailsTab extends BottomTab<DebugSliceDetalsTabConfig> {
+export class DebugSliceDetailsTab extends
+ BottomTab<DebugSliceDetailsTabConfig> {
static readonly kind = 'org.perfetto.DebugSliceDetailsTab';
data: {[key: string]: ColumnType}|undefined;
@@ -78,12 +70,11 @@
if (this.data === undefined) {
return m('h2', 'Loading');
}
- // TODO(stevegolton): These type assertions are dangerous, but no more
- // dangerous than they used to be before this change.
const left = dictToTree({
'Name': this.data['name'] as string,
- 'Start time': m(Timestamp, {ts: timestampFromSqlNanos(this.data['ts'])}),
- 'Duration': m(Duration, {dur: Number(this.data['dur'])}),
+ 'Start time':
+ m(Timestamp, {ts: asTPTimestamp(tpTimeFromSql(this.data['ts']))}),
+ 'Duration': m(Duration, {dur: tpDurationFromSql(this.data['dur'])}),
'Debug slice id': `${this.config.sqlTableName}[${this.config.id}]`,
});
const args: {[key: string]: m.Child} = {};
@@ -93,7 +84,7 @@
}
}
return m(
- 'div.details-panel',
+ '.details-panel',
m('header.overview', m('span', 'Debug Slice')),
m('.details-table-multicolumn',
{
diff --git a/ui/src/tracks/debug/slice_track.ts b/ui/src/tracks/debug/slice_track.ts
index a871a9f..664840d 100644
--- a/ui/src/tracks/debug/slice_track.ts
+++ b/ui/src/tracks/debug/slice_track.ts
@@ -78,8 +78,8 @@
globals.dispatch(Actions.selectDebugSlice({
id: args.slice.id,
sqlTableName: this.config.sqlTableName,
- startS: args.slice.startS,
- durationS: args.slice.durationS,
+ start: args.slice.start,
+ duration: args.slice.duration,
trackId: this.trackId,
}));
}
diff --git a/ui/src/tracks/expected_frames/index.ts b/ui/src/tracks/expected_frames/index.ts
index f2ab086..f7e5121 100644
--- a/ui/src/tracks/expected_frames/index.ts
+++ b/ui/src/tracks/expected_frames/index.ts
@@ -19,8 +19,8 @@
import {NewTrackArgs, Track} from '../../frontend/track';
import {ChromeSliceTrack} from '../chrome_slices';
-import {NUM, NUM_NULL, STR} from '../../common/query_result';
-import {fromNs, toNs} from '../../common/time';
+import {LONG_NULL, NUM, STR} from '../../common/query_result';
+import {TPDuration, TPTime, fromNs} from '../../common/time';
import {
TrackController,
} from '../../controller/track_controller';
@@ -46,27 +46,25 @@
class ExpectedFramesSliceTrackController extends TrackController<Config, Data> {
static readonly kind = EXPECTED_FRAMES_SLICE_TRACK_KIND;
- private maxDurNs = 0;
+ private maxDurNs: TPDuration = 0n;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
- const startNs = toNs(start);
- const endNs = toNs(end);
-
const pxSize = this.pxSize();
// ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
// be an even number, so we can snap in the middle.
- const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
+ const bucketNs =
+ Math.max(Math.round(Number(resolution) * pxSize / 2) * 2, 1);
- if (this.maxDurNs === 0) {
+ if (this.maxDurNs === 0n) {
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(',')}'
`);
- this.maxDurNs = maxDurResult.firstRow({maxDur: NUM_NULL}).maxDur || 0;
+ this.maxDurNs = maxDurResult.firstRow({maxDur: LONG_NULL}).maxDur || 0n;
}
const queryRes = await this.query(`
@@ -82,8 +80,8 @@
from experimental_slice_layout
where
filter_track_ids = '${this.config.trackIds.join(',')}' and
- ts >= ${startNs - this.maxDurNs} and
- ts <= ${endNs}
+ ts >= ${start - this.maxDurNs} and
+ ts <= ${end}
group by tsq, layout_depth
order by tsq, layout_depth
`);
diff --git a/ui/src/tracks/ftrace/index.ts b/ui/src/tracks/ftrace/index.ts
index e5913fa..8cd40f3 100644
--- a/ui/src/tracks/ftrace/index.ts
+++ b/ui/src/tracks/ftrace/index.ts
@@ -17,7 +17,8 @@
import {colorForString} from '../../common/colorizer';
import {PluginContext} from '../../common/plugin_api';
import {NUM, STR} from '../../common/query_result';
-import {fromNs, toNsCeil, toNsFloor} from '../../common/time';
+import {fromNs, TPDuration} from '../../common/time';
+import {TPTime} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {LIMIT} from '../../common/track_data';
import {
@@ -46,14 +47,8 @@
class FtraceRawTrackController extends TrackController<Config, Data> {
static readonly kind = FTRACE_RAW_TRACK_KIND;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
- const startNs = toNsFloor(start);
- const endNs = toNsCeil(end);
-
- // |resolution| is in s/px the frontend wants.
- const quantNs = toNsCeil(resolution);
-
const excludeList = Array.from(globals.state.ftraceFilter.excludedNames);
const excludeListSql = excludeList.map((s) => `'${s}'`).join(',');
const cpuFilter =
@@ -61,13 +56,13 @@
const queryRes = await this.query(`
select
- cast(ts / ${quantNs} as integer) * ${quantNs} as tsQuant,
+ cast(ts / ${resolution} as integer) * ${resolution} as tsQuant,
type,
name
from ftrace_event
where
name not in (${excludeListSql}) and
- ts >= ${startNs} and ts <= ${endNs} ${cpuFilter}
+ ts >= ${start} and ts <= ${end} ${cpuFilter}
group by tsQuant
order by tsQuant limit ${LIMIT};`);
@@ -107,16 +102,19 @@
}
renderCanvas(ctx: CanvasRenderingContext2D): void {
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {
+ visibleTimeScale,
+ windowSpan,
+ } = globals.frontendLocalState;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
- const dataStartPx = timeScale.timeToPx(data.start);
- const dataEndPx = timeScale.timeToPx(data.end);
- const visibleStartPx = timeScale.timeToPx(visibleWindowTime.start);
- const visibleEndPx = timeScale.timeToPx(visibleWindowTime.end);
+ const dataStartPx = visibleTimeScale.tpTimeToPx(data.start);
+ const dataEndPx = visibleTimeScale.tpTimeToPx(data.end);
+ const visibleStartPx = windowSpan.start;
+ const visibleEndPx = windowSpan.end;
checkerboardExcept(
ctx,
@@ -137,7 +135,7 @@
${Math.min(color.l + 10, 60)}%
)`;
ctx.fillStyle = hsl;
- const xPos = Math.floor(timeScale.timeToPx(data.timestamps[i]));
+ const xPos = Math.floor(visibleTimeScale.secondsToPx(data.timestamps[i]));
// Draw a diamond over the event
ctx.save();
diff --git a/ui/src/tracks/heap_profile/index.ts b/ui/src/tracks/heap_profile/index.ts
index b3eb40a..3e656f0 100644
--- a/ui/src/tracks/heap_profile/index.ts
+++ b/ui/src/tracks/heap_profile/index.ts
@@ -18,7 +18,13 @@
import {Actions} from '../../common/actions';
import {PluginContext} from '../../common/plugin_api';
import {NUM, STR} from '../../common/query_result';
-import {fromNs, toNs} from '../../common/time';
+import {
+ fromNs,
+ TPDuration,
+ TPTime,
+ tpTimeFromNanos,
+ tpTimeFromSeconds,
+} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {profileType} from '../../controller/flamegraph_controller';
import {
@@ -42,7 +48,7 @@
class HeapProfileTrackController extends TrackController<Config, Data> {
static readonly kind = HEAP_PROFILE_TRACK_KIND;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
if (this.config.upid === undefined) {
return {
@@ -111,7 +117,7 @@
renderCanvas(ctx: CanvasRenderingContext2D): void {
const {
- timeScale,
+ visibleTimeScale: timeScale,
} = globals.frontendLocalState;
const data = this.data();
@@ -122,11 +128,12 @@
const selection = globals.state.currentSelection;
const isHovered = this.hoveredTs === centerX;
const isSelected = selection !== null &&
- selection.kind === 'HEAP_PROFILE' && selection.ts === centerX;
+ selection.kind === 'HEAP_PROFILE' &&
+ selection.ts === tpTimeFromSeconds(centerX);
const strokeWidth = isSelected ? 3 : 0;
this.drawMarker(
ctx,
- timeScale.timeToPx(fromNs(centerX)),
+ timeScale.secondsToPx(fromNs(centerX)),
this.centerY,
isHovered,
strokeWidth);
@@ -155,8 +162,10 @@
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 {
+ visibleTimeScale: timeScale,
+ } = globals.frontendLocalState;
+ const time = timeScale.pxToHpTime(x).nanos;
const [left, right] = searchSegment(data.tsStarts, time);
const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
this.hoveredTs = index === -1 ? undefined : data.tsStarts[index];
@@ -169,15 +178,18 @@
onMouseClick({x, y}: {x: number, y: number}) {
const data = this.data();
if (data === undefined) return false;
- const {timeScale} = globals.frontendLocalState;
+ const {
+ visibleTimeScale: timeScale,
+ } = globals.frontendLocalState;
- const time = toNs(timeScale.pxToTime(x));
+ const time = timeScale.pxToHpTime(x).nanos;
const [left, right] = searchSegment(data.tsStarts, time);
const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
if (index !== -1) {
- const ts = data.tsStarts[index];
+ // TODO(stevegolton): Remove conversion from number to bigint.
+ const ts = tpTimeFromNanos(data.tsStarts[index]);
const type = data.types[index];
globals.makeSelection(Actions.selectHeapProfile(
{id: index, upid: this.config.upid, ts, type}));
@@ -192,13 +204,13 @@
right: number): number {
let index = -1;
if (left !== -1) {
- const centerX = timeScale.timeToPx(fromNs(data.tsStarts[left]));
+ const centerX = timeScale.secondsToPx(fromNs(data.tsStarts[left]));
if (this.isInMarker(x, y, centerX)) {
index = left;
}
}
if (right !== -1) {
- const centerX = timeScale.timeToPx(fromNs(data.tsStarts[right]));
+ const centerX = timeScale.secondsToPx(fromNs(data.tsStarts[right]));
if (this.isInMarker(x, y, centerX)) {
index = right;
}
diff --git a/ui/src/tracks/perf_samples_profile/index.ts b/ui/src/tracks/perf_samples_profile/index.ts
index cfc73dd..693e295 100644
--- a/ui/src/tracks/perf_samples_profile/index.ts
+++ b/ui/src/tracks/perf_samples_profile/index.ts
@@ -17,7 +17,12 @@
import {PluginContext} from '../../common/plugin_api';
import {NUM} from '../../common/query_result';
import {ProfileType} from '../../common/state';
-import {fromNs, toNs} from '../../common/time';
+import {
+ fromNs,
+ TPDuration,
+ TPTime,
+ tpTimeFromSeconds,
+} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {
TrackController,
@@ -39,7 +44,7 @@
class PerfSamplesProfileTrackController extends TrackController<Config, Data> {
static readonly kind = PERF_SAMPLES_PROFILE_TRACK_KIND;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
if (this.config.upid === undefined) {
return {
@@ -99,7 +104,7 @@
renderCanvas(ctx: CanvasRenderingContext2D): void {
const {
- timeScale,
+ visibleTimeScale,
} = globals.frontendLocalState;
const data = this.data();
@@ -115,7 +120,7 @@
const strokeWidth = isSelected ? 3 : 0;
this.drawMarker(
ctx,
- timeScale.timeToPx(fromNs(centerX)),
+ visibleTimeScale.secondsToPx(fromNs(centerX)),
this.centerY,
isHovered,
strokeWidth);
@@ -144,10 +149,11 @@
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 {visibleTimeScale} = globals.frontendLocalState;
+ const time = visibleTimeScale.pxToHpTime(x).nanos;
const [left, right] = searchSegment(data.tsStartsNs, time);
- const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
+ const index =
+ this.findTimestampIndex(left, visibleTimeScale, data, x, y, right);
this.hoveredTs = index === -1 ? undefined : data.tsStartsNs[index];
}
@@ -158,9 +164,11 @@
onMouseClick({x, y}: {x: number, y: number}) {
const data = this.data();
if (data === undefined) return false;
- const {timeScale} = globals.frontendLocalState;
+ const {
+ visibleTimeScale: timeScale,
+ } = globals.frontendLocalState;
- const time = toNs(timeScale.pxToTime(x));
+ const time = timeScale.pxToHpTime(x).nanos;
const [left, right] = searchSegment(data.tsStartsNs, time);
const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
@@ -170,8 +178,8 @@
globals.makeSelection(Actions.selectPerfSamples({
id: index,
upid: this.config.upid,
- leftTs: ts,
- rightTs: ts,
+ leftTs: tpTimeFromSeconds(ts),
+ rightTs: tpTimeFromSeconds(ts),
type: ProfileType.PERF_SAMPLE,
}));
return true;
@@ -185,13 +193,13 @@
right: number): number {
let index = -1;
if (left !== -1) {
- const centerX = timeScale.timeToPx(fromNs(data.tsStartsNs[left]));
+ const centerX = timeScale.secondsToPx(fromNs(data.tsStartsNs[left]));
if (this.isInMarker(x, y, centerX)) {
index = left;
}
}
if (right !== -1) {
- const centerX = timeScale.timeToPx(fromNs(data.tsStartsNs[right]));
+ const centerX = timeScale.secondsToPx(fromNs(data.tsStartsNs[right]));
if (this.isInMarker(x, y, centerX)) {
index = right;
}
diff --git a/ui/src/tracks/process_scheduling/index.ts b/ui/src/tracks/process_scheduling/index.ts
index 95302b6..d88bc71 100644
--- a/ui/src/tracks/process_scheduling/index.ts
+++ b/ui/src/tracks/process_scheduling/index.ts
@@ -12,13 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {BigintMath} from '../../base/bigint_math';
import {searchEq, searchRange, searchSegment} from '../../base/binary_search';
import {assertTrue} from '../../base/logging';
import {Actions} from '../../common/actions';
import {colorForThread} from '../../common/colorizer';
import {PluginContext} from '../../common/plugin_api';
import {NUM, QueryResult} from '../../common/query_result';
-import {fromNs, toNs} from '../../common/time';
+import {
+ fromNs,
+ TPDuration,
+ TPTime,
+ tpTimeFromSeconds,
+ tpTimeToNanos,
+} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {
TrackController,
@@ -91,22 +98,23 @@
this.cachedBucketNs = bucketNs;
}
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
assertTrue(this.config.upid !== null);
// The resolution should always be a power of two for the logic of this
// function to make sense.
- const resolutionNs = toNs(resolution);
- assertTrue(Math.log2(resolutionNs) % 1 === 0);
+ assertTrue(
+ BigintMath.popcount(resolution) === 1,
+ `${resolution} is not a power of 2`);
- const startNs = toNs(start);
- const endNs = toNs(end);
+ const startNs = tpTimeToNanos(start);
+ const endNs = tpTimeToNanos(end);
// ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
// be an even number, so we can snap in the middle.
const bucketNs =
- Math.max(Math.round(resolutionNs * this.pxSize() / 2) * 2, 1);
+ Math.max(Math.round(Number(resolution) * this.pxSize() / 2) * 2, 1);
const queryRes = await this.queryData(startNs, endNs, bucketNs);
const numRows = queryRes.numRows();
@@ -144,7 +152,8 @@
slices.ends[row] = fromNs(endNsQ);
slices.cpus[row] = it.cpu;
slices.utids[row] = it.utid;
- slices.end = Math.max(slices.ends[row], slices.end);
+ slices.end =
+ BigintMath.max(tpTimeFromSeconds(slices.ends[row]), slices.end);
}
return slices;
}
@@ -208,7 +217,10 @@
renderCanvas(ctx: CanvasRenderingContext2D): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {
+ visibleTimeScale,
+ visibleWindowTime,
+ } = globals.frontendLocalState;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
@@ -218,19 +230,20 @@
checkerboardExcept(
ctx,
this.getHeight(),
- timeScale.timeToPx(visibleWindowTime.start),
- timeScale.timeToPx(visibleWindowTime.end),
- timeScale.timeToPx(data.start),
- timeScale.timeToPx(data.end));
+ visibleTimeScale.hpTimeToPx(visibleWindowTime.start),
+ visibleTimeScale.hpTimeToPx(visibleWindowTime.end),
+ visibleTimeScale.tpTimeToPx(data.start),
+ visibleTimeScale.tpTimeToPx(data.end));
assertTrue(data.starts.length === data.ends.length);
assertTrue(data.starts.length === data.utids.length);
- const rawStartIdx =
- data.ends.findIndex((end) => end >= visibleWindowTime.start);
+ const startSeconds = visibleWindowTime.start.seconds;
+ const rawStartIdx = data.ends.findIndex((end) => end >= startSeconds);
const startIdx = rawStartIdx === -1 ? data.starts.length : rawStartIdx;
- const [, rawEndIdx] = searchSegment(data.starts, visibleWindowTime.end);
+ const [, rawEndIdx] =
+ searchSegment(data.starts, visibleWindowTime.end.seconds);
const endIdx = rawEndIdx === -1 ? data.starts.length : rawEndIdx;
const cpuTrackHeight = Math.floor(RECT_HEIGHT / data.maxCpu);
@@ -241,8 +254,8 @@
const utid = data.utids[i];
const cpu = data.cpus[i];
- const rectStart = timeScale.timeToPx(tStart);
- const rectEnd = timeScale.timeToPx(tEnd);
+ const rectStart = visibleTimeScale.secondsToPx(tStart);
+ const rectEnd = visibleTimeScale.secondsToPx(tEnd);
const rectWidth = rectEnd - rectStart;
if (rectWidth < 0.3) continue;
@@ -294,8 +307,8 @@
const cpuTrackHeight = Math.floor(RECT_HEIGHT / data.maxCpu);
const cpu = Math.floor((pos.y - MARGIN_TOP) / (cpuTrackHeight + 1));
- const {timeScale} = globals.frontendLocalState;
- const t = timeScale.pxToTime(pos.x);
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const t = visibleTimeScale.pxToHpTime(pos.x).seconds;
const [i, j] = searchRange(data.starts, t, searchEq(data.cpus, cpu));
if (i === j || i >= data.starts.length || t > data.ends[i]) {
diff --git a/ui/src/tracks/process_summary/index.ts b/ui/src/tracks/process_summary/index.ts
index d2d0ee8..8b92511 100644
--- a/ui/src/tracks/process_summary/index.ts
+++ b/ui/src/tracks/process_summary/index.ts
@@ -15,7 +15,14 @@
import {colorForTid} from '../../common/colorizer';
import {PluginContext} from '../../common/plugin_api';
import {NUM} from '../../common/query_result';
-import {fromNs, toNs} from '../../common/time';
+import {
+ fromNs,
+ TPDuration,
+ TPTime,
+ tpTimeFromNanos,
+ tpTimeToNanos,
+ tpTimeToSeconds,
+} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {LIMIT} from '../../common/track_data';
import {
@@ -45,10 +52,10 @@
static readonly kind = PROCESS_SUMMARY_TRACK;
private setup = false;
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
- const startNs = toNs(start);
- const endNs = toNs(end);
+ const startNs = tpTimeToNanos(start);
+ const endNs = tpTimeToNanos(end);
if (this.setup === false) {
await this.query(
@@ -85,9 +92,9 @@
this.setup = true;
}
- // |resolution| is in s/px we want # ns for 10px window:
+ // |resolution| is in ns/px we want # ns for 10px window:
// Max value with 1 so we don't end up with resolution 0.
- const bucketSizeNs = Math.max(1, Math.round(resolution * 10 * 1e9));
+ const bucketSizeNs = Math.max(1, Math.round(Number(resolution) * 10));
const windowStartNs = Math.floor(startNs / bucketSizeNs) * bucketSizeNs;
const windowDurNs = Math.max(1, endNs - windowStartNs);
@@ -98,14 +105,14 @@
where rowid = 0;`);
return this.computeSummary(
- fromNs(windowStartNs), end, resolution, bucketSizeNs);
+ tpTimeFromNanos(windowStartNs), end, resolution, bucketSizeNs);
}
private async computeSummary(
- start: number, end: number, resolution: number,
+ start: TPTime, end: TPTime, resolution: TPDuration,
bucketSizeNs: number): Promise<Data> {
- const startNs = toNs(start);
- const endNs = toNs(end);
+ const startNs = Number(start);
+ const endNs = Number(end);
const numBuckets =
Math.min(Math.ceil((endNs - startNs) / bucketSizeNs), LIMIT);
@@ -167,25 +174,28 @@
}
renderCanvas(ctx: CanvasRenderingContext2D): void {
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {
+ visibleTimeScale,
+ windowSpan,
+ } = globals.frontendLocalState;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
checkerboardExcept(
ctx,
this.getHeight(),
- timeScale.timeToPx(visibleWindowTime.start),
- timeScale.timeToPx(visibleWindowTime.end),
- timeScale.timeToPx(data.start),
- timeScale.timeToPx(data.end));
+ windowSpan.start,
+ windowSpan.end,
+ visibleTimeScale.tpTimeToPx(data.start),
+ visibleTimeScale.tpTimeToPx(data.end));
this.renderSummary(ctx, data);
}
// TODO(dproy): Dedup with CPU slices.
renderSummary(ctx: CanvasRenderingContext2D, data: Data): void {
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
- const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
+ const {visibleTimeScale, windowSpan} = globals.frontendLocalState;
+ const startPx = windowSpan.start;
const bottomY = TRACK_HEIGHT;
let lastX = startPx;
@@ -202,9 +212,10 @@
for (let i = 0; i < data.utilizations.length; i++) {
// TODO(dproy): Investigate why utilization is > 1 sometimes.
const utilization = Math.min(data.utilizations[i], 1);
- const startTime = i * data.bucketSizeSeconds + data.start;
+ const startTime =
+ i * data.bucketSizeSeconds + tpTimeToSeconds(data.start);
- lastX = Math.floor(timeScale.timeToPx(startTime));
+ lastX = Math.floor(visibleTimeScale.secondsToPx(startTime));
ctx.lineTo(lastX, lastY);
lastY = MARGIN_TOP + Math.round(SUMMARY_HEIGHT * (1 - utilization));
diff --git a/ui/src/tracks/scroll_jank/event_latency_track.ts b/ui/src/tracks/scroll_jank/event_latency_track.ts
new file mode 100644
index 0000000..d805e74
--- /dev/null
+++ b/ui/src/tracks/scroll_jank/event_latency_track.ts
@@ -0,0 +1,83 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {v4 as uuidv4} from 'uuid';
+
+import {Engine} from '../../common/engine';
+import {
+ generateSqlWithInternalLayout,
+} from '../../common/internal_layout_utils';
+import {PrimaryTrackSortKey, SCROLLING_TRACK_GROUP} from '../../common/state';
+import {
+ NamedSliceTrack,
+ NamedSliceTrackTypes,
+} from '../../frontend/named_slice_track';
+import {NewTrackArgs, Track} from '../../frontend/track';
+import {DecideTracksResult} from '../chrome_scroll_jank';
+
+interface EventLatencyTrackTypes extends NamedSliceTrackTypes {}
+
+export class EventLatencyTrack extends NamedSliceTrack<EventLatencyTrackTypes> {
+ static readonly kind = 'org.chromium.ScrollJank.event_latencies';
+ createdModels = false;
+
+ static create(args: NewTrackArgs): Track {
+ return new EventLatencyTrack(args);
+ }
+
+ constructor(args: NewTrackArgs) {
+ super(args);
+ }
+
+ async initSqlTable(tableName: string) {
+ if (this.createdModels) {
+ return;
+ }
+ const sql = `CREATE VIEW ${tableName} AS ` + generateSqlWithInternalLayout({
+ columns: ['id', 'ts', 'dur', 'track_id', 'name'],
+ layoutParams: {ts: 'ts', dur: 'dur'},
+ sourceTable: 'slice',
+ whereClause: 'slice.id IN ' +
+ '(SELECT slice_id FROM event_latency_scroll_jank_cause)',
+ });
+ await this.engine.query(sql);
+ this.createdModels = true;
+ }
+
+ // At the moment we will just display the slice details. However, on select,
+ // this behavior should be customized to show jank-related data.
+}
+
+export async function addLatenciesTrack(engine: Engine):
+ Promise<DecideTracksResult> {
+ const result: DecideTracksResult = {
+ tracksToAdd: [],
+ };
+
+ await engine.query(`
+ SELECT RUN_METRIC('chrome/event_latency_scroll_jank_cause.sql');
+ `);
+
+ result.tracksToAdd.push({
+ id: uuidv4(),
+ engineId: engine.id,
+ kind: EventLatencyTrack.kind,
+ trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
+ name: 'Scroll Janks',
+ config: {},
+ trackGroup: SCROLLING_TRACK_GROUP,
+ });
+
+ return result;
+}
diff --git a/ui/src/tracks/scroll_jank/index.ts b/ui/src/tracks/scroll_jank/index.ts
new file mode 100644
index 0000000..5f6d86b
--- /dev/null
+++ b/ui/src/tracks/scroll_jank/index.ts
@@ -0,0 +1,63 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {featureFlags} from '../../common/feature_flags';
+import {PluginContext} from '../../common/plugin_api';
+import {Selection} from '../../common/state';
+import {CURRENT_SELECTION_TAG} from '../../frontend/details_panel';
+import {globals} from '../../frontend/globals';
+
+import {EventLatencyTrack} from './event_latency_track';
+import {TopLevelScrollDetailsTab} from './scroll_details_tab';
+import {
+ TOP_LEVEL_SCROLL_KIND,
+ TopLevelScrollTrack,
+} from './scroll_track';
+
+export const INPUT_LATENCY_TRACK = 'InputLatency::';
+export const SCROLL_JANK_PLUGIN_ID = 'perfetto.ScrollJank';
+export const ENABLE_SCROLL_JANK_PLUGIN_V2 = featureFlags.register({
+ id: 'enableScrollJankPluginV2',
+ name: 'Enable Scroll Jank plugin V2',
+ description: 'Adds new tracks and visualizations for scroll jank.',
+ defaultValue: false,
+});
+
+function onDetailsPanelSelectionChange(newSelection?: Selection) {
+ if (newSelection === undefined ||
+ newSelection.kind !== TOP_LEVEL_SCROLL_KIND) {
+ return;
+ }
+ const bottomTabList = globals.bottomTabList;
+ if (!bottomTabList) return;
+ bottomTabList.addTab({
+ kind: TopLevelScrollDetailsTab.kind,
+ tag: CURRENT_SELECTION_TAG,
+ config: {
+ sqlTableName: newSelection.sqlTableName,
+ id: newSelection.id,
+ },
+ });
+}
+
+function activate(ctx: PluginContext) {
+ ctx.registerTrack(TopLevelScrollTrack);
+ ctx.registerTrack(EventLatencyTrack);
+ ctx.registerOnDetailsPanelSelectionChange(onDetailsPanelSelectionChange);
+}
+
+export const plugin = {
+ pluginId: SCROLL_JANK_PLUGIN_ID,
+ activate,
+};
diff --git a/ui/src/tracks/scroll_jank/scroll_details_tab.ts b/ui/src/tracks/scroll_jank/scroll_details_tab.ts
new file mode 100644
index 0000000..b13fcae
--- /dev/null
+++ b/ui/src/tracks/scroll_jank/scroll_details_tab.ts
@@ -0,0 +1,90 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Panel for the top-level scrolls. For now, just show the scroll id, but we
+// can add things like scroll event count, janks, etc. as needed.
+
+import m from 'mithril';
+
+import {ColumnType} from '../../common/query_result';
+import {tpDurationFromSql, tpTimeFromSql} from '../../common/time';
+import {
+ BottomTab,
+ bottomTabRegistry,
+ NewBottomTabArgs,
+} from '../../frontend/bottom_tab';
+import {globals} from '../../frontend/globals';
+import {asTPTimestamp} from '../../frontend/sql_types';
+import {Duration} from '../../frontend/widgets/duration';
+import {Timestamp} from '../../frontend/widgets/timestamp';
+import {dictToTree} from '../../frontend/widgets/tree';
+
+interface TopLevelScrollTabConfig {
+ sqlTableName: string;
+ id: number;
+}
+
+export class TopLevelScrollDetailsTab extends
+ BottomTab<TopLevelScrollTabConfig> {
+ static readonly kind = 'org.perfetto.TopLevelScrollDetailsTab';
+
+ data: {[key: string]: ColumnType}|undefined;
+
+ static create(args: NewBottomTabArgs): TopLevelScrollDetailsTab {
+ return new TopLevelScrollDetailsTab(args);
+ }
+
+ constructor(args: NewBottomTabArgs) {
+ super(args);
+
+ this.engine
+ .query(`select * from ${this.config.sqlTableName} where id = ${
+ this.config.id}`)
+ .then((queryResult) => {
+ this.data = queryResult.firstRow({});
+ globals.rafScheduler.scheduleFullRedraw();
+ });
+ }
+
+ viewTab() {
+ if (this.data === undefined) {
+ return m('h2', 'Loading');
+ }
+
+ const left = dictToTree({
+ 'Scroll Id (gesture_scroll_id)': `${this.data['id']}`,
+ 'Start time':
+ m(Timestamp, {ts: asTPTimestamp(tpTimeFromSql(this.data['ts']))}),
+ 'Duration': m(Duration, {dur: tpDurationFromSql(this.data['dur'])}),
+ });
+ return m(
+ '.details-panel',
+ m('header.overview', m('span', `${this.data['name']}`)),
+ m('.details-table-multicolumn', m('.half-width-panel', left)));
+ }
+
+ getTitle(): string {
+ return `Current Chrome Scroll`;
+ }
+
+ isLoading() {
+ return this.data === undefined;
+ }
+
+ renderTabCanvas() {
+ return;
+ }
+}
+
+bottomTabRegistry.register(TopLevelScrollDetailsTab);
diff --git a/ui/src/tracks/scroll_jank/scroll_track.ts b/ui/src/tracks/scroll_jank/scroll_track.ts
new file mode 100644
index 0000000..8532a45
--- /dev/null
+++ b/ui/src/tracks/scroll_jank/scroll_track.ts
@@ -0,0 +1,116 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {TPTime} from 'src/common/time';
+import {v4 as uuidv4} from 'uuid';
+
+import {Actions} from '../../common/actions';
+import {Engine} from '../../common/engine';
+import {
+ generateSqlWithInternalLayout,
+} from '../../common/internal_layout_utils';
+import {
+ PrimaryTrackSortKey,
+ SCROLLING_TRACK_GROUP,
+ Selection,
+} from '../../common/state';
+import {OnSliceClickArgs} from '../../frontend/base_slice_track';
+import {globals} from '../../frontend/globals';
+import {
+ NamedSliceTrack,
+ NamedSliceTrackTypes,
+} from '../../frontend/named_slice_track';
+import {NewTrackArgs, Track} from '../../frontend/track';
+import {DecideTracksResult} from '../chrome_scroll_jank';
+
+export const TOP_LEVEL_SCROLL_KIND = 'TOP_LEVEL_SCROLL';
+
+export interface TopLevelScrollSelection {
+ kind: 'TOP_LEVEL_SCROLL';
+ id: number;
+ sqlTableName: string;
+ start: TPTime;
+ duration: TPTime;
+}
+
+export {Data} from '../chrome_slices';
+
+interface TopLevelScrollTrackTypes extends NamedSliceTrackTypes {}
+
+export class TopLevelScrollTrack extends
+ NamedSliceTrack<TopLevelScrollTrackTypes> {
+ static readonly kind = 'org.chromium.TopLevelScrolls.scrolls';
+ createdModels = false;
+
+ static create(args: NewTrackArgs): Track {
+ return new TopLevelScrollTrack(args);
+ }
+
+ constructor(args: NewTrackArgs) {
+ super(args);
+ }
+
+ async initSqlTable(tableName: string) {
+ if (this.createdModels) {
+ return;
+ }
+ const sql =
+ `CREATE VIEW ${tableName} AS ` + generateSqlWithInternalLayout({
+ columns: [`printf("Scroll %s", CAST(id AS STRING)) AS name`, '*'],
+ layoutParams: {ts: 'ts', dur: 'dur'},
+ sourceTable: 'chrome_scrolls',
+ orderByClause: 'ts',
+ });
+ await this.engine.query(sql);
+ this.createdModels = true;
+ }
+
+ isSelectionHandled(selection: Selection) {
+ if (selection.kind !== 'TOP_LEVEL_SCROLL') {
+ return false;
+ }
+ return selection.trackId === this.trackId;
+ }
+
+ onSliceClick(args: OnSliceClickArgs<TopLevelScrollTrackTypes['slice']>) {
+ globals.dispatch(Actions.selectTopLevelScrollSlice({
+ id: args.slice.id,
+ sqlTableName: this.tableName,
+ start: args.slice.start,
+ duration: args.slice.duration,
+ trackId: this.trackId,
+ }));
+ }
+}
+
+export async function addTopLevelScrollTrack(engine: Engine):
+ Promise<DecideTracksResult> {
+ const result: DecideTracksResult = {
+ tracksToAdd: [],
+ };
+
+ await engine.query(`SELECT IMPORT('chrome.chrome_scrolls');`);
+
+ result.tracksToAdd.push({
+ id: uuidv4(),
+ engineId: engine.id,
+ kind: TopLevelScrollTrack.kind,
+ trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
+ name: 'Top Level Scrolls',
+ config: {},
+ trackGroup: SCROLLING_TRACK_GROUP,
+ });
+
+ return result;
+}
diff --git a/ui/src/tracks/thread_state/index.ts b/ui/src/tracks/thread_state/index.ts
index 3713999..4ad1b4c 100644
--- a/ui/src/tracks/thread_state/index.ts
+++ b/ui/src/tracks/thread_state/index.ts
@@ -17,10 +17,18 @@
import {Actions} from '../../common/actions';
import {cropText} from '../../common/canvas_utils';
import {colorForState} from '../../common/colorizer';
+import {
+ HighPrecisionTime,
+ HighPrecisionTimeSpan,
+} from '../../common/high_precision_time';
import {PluginContext} from '../../common/plugin_api';
-import {NUM, NUM_NULL, STR_NULL} from '../../common/query_result';
+import {LONG, NUM, NUM_NULL, STR_NULL} from '../../common/query_result';
import {translateState} from '../../common/thread_state';
-import {fromNs, toNs} from '../../common/time';
+import {
+ fromNs,
+ TPDuration,
+ TPTime,
+} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {TrackController} from '../../controller/track_controller';
import {checkerboardExcept} from '../../frontend/checkerboard';
@@ -46,7 +54,7 @@
class ThreadStateTrackController extends TrackController<Config, Data> {
static readonly kind = THREAD_STATE_TRACK_KIND;
- private maxDurNs = 0;
+ private maxDurNs: TPDuration = 0n;
async onSetup() {
await this.query(`
@@ -66,19 +74,15 @@
select ifnull(max(dur), 0) as maxDur
from ${this.tableName('thread_state')}
`);
- this.maxDurNs = queryRes.firstRow({maxDur: NUM}).maxDur;
+ this.maxDurNs = queryRes.firstRow({maxDur: LONG}).maxDur;
}
- async onBoundsChange(start: number, end: number, resolution: number):
+ async onBoundsChange(start: TPTime, end: TPTime, resolution: TPDuration):
Promise<Data> {
- const resolutionNs = toNs(resolution);
- const startNs = toNs(start);
- const endNs = toNs(end);
-
// ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
// be an even number, so we can snap in the middle.
const bucketNs =
- Math.max(Math.round(resolutionNs * this.pxSize() / 2) * 2, 1);
+ Math.max(Math.round(Number(resolution) * this.pxSize() / 2) * 2, 1);
const query = `
select
@@ -92,8 +96,8 @@
ifnull(id, -1) as id
from ${this.tableName('thread_state')}
where
- ts >= ${startNs - this.maxDurNs} and
- ts <= ${endNs}
+ ts >= ${start - this.maxDurNs} and
+ ts <= ${end}
group by tsq, is_sleep
order by tsq
`;
@@ -186,7 +190,11 @@
}
renderCanvas(ctx: CanvasRenderingContext2D): void {
- const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {
+ visibleTimeScale: timeScale,
+ visibleWindowTime,
+ windowSpan,
+ } = globals.frontendLocalState;
const data = this.data();
const charWidth = ctx.measureText('dbpqaouk').width / 8;
@@ -199,10 +207,10 @@
checkerboardExcept(
ctx,
this.getHeight(),
- timeScale.timeToPx(visibleWindowTime.start),
- timeScale.timeToPx(visibleWindowTime.end),
- timeScale.timeToPx(data.start),
- timeScale.timeToPx(data.end),
+ windowSpan.start,
+ windowSpan.end,
+ timeScale.tpTimeToPx(data.start),
+ timeScale.tpTimeToPx(data.end),
);
ctx.textAlign = 'center';
@@ -220,14 +228,19 @@
const tStart = data.starts[i];
const tEnd = data.ends[i];
const state = data.strings[data.state[i]];
- if (tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end) {
+ const timeSpan = new HighPrecisionTimeSpan(
+ HighPrecisionTime.fromSeconds(tStart),
+ HighPrecisionTime.fromSeconds(tEnd),
+ );
+
+ if (!visibleWindowTime.intersects(timeSpan)) {
continue;
}
// Don't display a slice for Task Dead.
if (state === 'x') continue;
- const rectStart = timeScale.timeToPx(tStart);
- const rectEnd = timeScale.timeToPx(tEnd);
+ const rectStart = timeScale.secondsToPx(tStart);
+ const rectEnd = timeScale.secondsToPx(tEnd);
const rectWidth = rectEnd - rectStart;
const currentSelection = globals.state.currentSelection;
@@ -255,10 +268,9 @@
if (isSelected) {
drawRectOnSelected = () => {
const rectStart =
- Math.max(0 - EXCESS_WIDTH, timeScale.timeToPx(tStart));
+ Math.max(0 - EXCESS_WIDTH, timeScale.secondsToPx(tStart));
const rectEnd = Math.min(
- timeScale.timeToPx(visibleWindowTime.end) + EXCESS_WIDTH,
- timeScale.timeToPx(tEnd));
+ windowSpan.end + EXCESS_WIDTH, timeScale.secondsToPx(tEnd));
const color = colorForState(state);
ctx.strokeStyle = `hsl(${color.h},${color.s}%,${color.l * 0.7}%)`;
ctx.beginPath();
@@ -278,9 +290,9 @@
onMouseClick({x}: {x: number}) {
const data = this.data();
if (data === undefined) return false;
- const {timeScale} = globals.frontendLocalState;
- const time = timeScale.pxToTime(x);
- const index = search(data.starts, time);
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const time = visibleTimeScale.pxToHpTime(x);
+ const index = search(data.starts, time.seconds);
if (index === -1) return false;
const id = data.ids[index];