Merge "[chrome] Register MetadataModule for kChromeTriggerFieldNumber" into main
diff --git a/Android.bp b/Android.bp
index 1683b53..6cb0053 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1320,6 +1320,7 @@
"protos/perfetto/config/android/android_system_property_config.proto",
"protos/perfetto/config/android/network_trace_config.proto",
"protos/perfetto/config/android/packages_list_config.proto",
+ "protos/perfetto/config/android/pixel_modem_config.proto",
"protos/perfetto/config/android/protolog_config.proto",
"protos/perfetto/config/android/surfaceflinger_layers_config.proto",
"protos/perfetto/config/android/surfaceflinger_transactions_config.proto",
@@ -2344,6 +2345,7 @@
":perfetto_src_trace_processor_importers_common_parser_types",
":perfetto_src_trace_processor_importers_common_trace_parser_hdr",
":perfetto_src_trace_processor_importers_etw_full",
+ ":perfetto_src_trace_processor_importers_etw_minimal",
":perfetto_src_trace_processor_importers_ftrace_ftrace_descriptors",
":perfetto_src_trace_processor_importers_ftrace_full",
":perfetto_src_trace_processor_importers_ftrace_minimal",
@@ -2889,6 +2891,7 @@
"protos/perfetto/config/android/android_system_property_config.proto",
"protos/perfetto/config/android/network_trace_config.proto",
"protos/perfetto/config/android/packages_list_config.proto",
+ "protos/perfetto/config/android/pixel_modem_config.proto",
"protos/perfetto/config/android/protolog_config.proto",
"protos/perfetto/config/android/surfaceflinger_layers_config.proto",
"protos/perfetto/config/android/surfaceflinger_transactions_config.proto",
@@ -2916,6 +2919,7 @@
"external/perfetto/protos/perfetto/config/android/android_system_property_config.gen.cc",
"external/perfetto/protos/perfetto/config/android/network_trace_config.gen.cc",
"external/perfetto/protos/perfetto/config/android/packages_list_config.gen.cc",
+ "external/perfetto/protos/perfetto/config/android/pixel_modem_config.gen.cc",
"external/perfetto/protos/perfetto/config/android/protolog_config.gen.cc",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_layers_config.gen.cc",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_transactions_config.gen.cc",
@@ -2943,6 +2947,7 @@
"external/perfetto/protos/perfetto/config/android/android_system_property_config.gen.h",
"external/perfetto/protos/perfetto/config/android/network_trace_config.gen.h",
"external/perfetto/protos/perfetto/config/android/packages_list_config.gen.h",
+ "external/perfetto/protos/perfetto/config/android/pixel_modem_config.gen.h",
"external/perfetto/protos/perfetto/config/android/protolog_config.gen.h",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_layers_config.gen.h",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_transactions_config.gen.h",
@@ -2965,6 +2970,7 @@
"protos/perfetto/config/android/android_system_property_config.proto",
"protos/perfetto/config/android/network_trace_config.proto",
"protos/perfetto/config/android/packages_list_config.proto",
+ "protos/perfetto/config/android/pixel_modem_config.proto",
"protos/perfetto/config/android/protolog_config.proto",
"protos/perfetto/config/android/surfaceflinger_layers_config.proto",
"protos/perfetto/config/android/surfaceflinger_transactions_config.proto",
@@ -2991,6 +2997,7 @@
"external/perfetto/protos/perfetto/config/android/android_system_property_config.pb.cc",
"external/perfetto/protos/perfetto/config/android/network_trace_config.pb.cc",
"external/perfetto/protos/perfetto/config/android/packages_list_config.pb.cc",
+ "external/perfetto/protos/perfetto/config/android/pixel_modem_config.pb.cc",
"external/perfetto/protos/perfetto/config/android/protolog_config.pb.cc",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_layers_config.pb.cc",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_transactions_config.pb.cc",
@@ -3017,6 +3024,7 @@
"external/perfetto/protos/perfetto/config/android/android_system_property_config.pb.h",
"external/perfetto/protos/perfetto/config/android/network_trace_config.pb.h",
"external/perfetto/protos/perfetto/config/android/packages_list_config.pb.h",
+ "external/perfetto/protos/perfetto/config/android/pixel_modem_config.pb.h",
"external/perfetto/protos/perfetto/config/android/protolog_config.pb.h",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_layers_config.pb.h",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_transactions_config.pb.h",
@@ -3039,6 +3047,7 @@
"protos/perfetto/config/android/android_system_property_config.proto",
"protos/perfetto/config/android/network_trace_config.proto",
"protos/perfetto/config/android/packages_list_config.proto",
+ "protos/perfetto/config/android/pixel_modem_config.proto",
"protos/perfetto/config/android/protolog_config.proto",
"protos/perfetto/config/android/surfaceflinger_layers_config.proto",
"protos/perfetto/config/android/surfaceflinger_transactions_config.proto",
@@ -3066,6 +3075,7 @@
"external/perfetto/protos/perfetto/config/android/android_system_property_config.pbzero.cc",
"external/perfetto/protos/perfetto/config/android/network_trace_config.pbzero.cc",
"external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.cc",
+ "external/perfetto/protos/perfetto/config/android/pixel_modem_config.pbzero.cc",
"external/perfetto/protos/perfetto/config/android/protolog_config.pbzero.cc",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_layers_config.pbzero.cc",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_transactions_config.pbzero.cc",
@@ -3093,6 +3103,7 @@
"external/perfetto/protos/perfetto/config/android/android_system_property_config.pbzero.h",
"external/perfetto/protos/perfetto/config/android/network_trace_config.pbzero.h",
"external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.h",
+ "external/perfetto/protos/perfetto/config/android/pixel_modem_config.pbzero.h",
"external/perfetto/protos/perfetto/config/android/protolog_config.pbzero.h",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_layers_config.pbzero.h",
"external/perfetto/protos/perfetto/config/android/surfaceflinger_transactions_config.pbzero.h",
@@ -3226,6 +3237,7 @@
"protos/perfetto/config/android/android_system_property_config.proto",
"protos/perfetto/config/android/network_trace_config.proto",
"protos/perfetto/config/android/packages_list_config.proto",
+ "protos/perfetto/config/android/pixel_modem_config.proto",
"protos/perfetto/config/android/protolog_config.proto",
"protos/perfetto/config/android/surfaceflinger_layers_config.proto",
"protos/perfetto/config/android/surfaceflinger_transactions_config.proto",
@@ -5394,6 +5406,7 @@
"protos/perfetto/trace/android/initial_display_state.proto",
"protos/perfetto/trace/android/network_trace.proto",
"protos/perfetto/trace/android/packages_list.proto",
+ "protos/perfetto/trace/android/pixel_modem_events.proto",
"protos/perfetto/trace/android/protolog.proto",
"protos/perfetto/trace/android/shell_transition.proto",
"protos/perfetto/trace/android/surfaceflinger_common.proto",
@@ -5426,6 +5439,7 @@
"external/perfetto/protos/perfetto/trace/android/initial_display_state.gen.cc",
"external/perfetto/protos/perfetto/trace/android/network_trace.gen.cc",
"external/perfetto/protos/perfetto/trace/android/packages_list.gen.cc",
+ "external/perfetto/protos/perfetto/trace/android/pixel_modem_events.gen.cc",
"external/perfetto/protos/perfetto/trace/android/protolog.gen.cc",
"external/perfetto/protos/perfetto/trace/android/shell_transition.gen.cc",
"external/perfetto/protos/perfetto/trace/android/surfaceflinger_common.gen.cc",
@@ -5458,6 +5472,7 @@
"external/perfetto/protos/perfetto/trace/android/initial_display_state.gen.h",
"external/perfetto/protos/perfetto/trace/android/network_trace.gen.h",
"external/perfetto/protos/perfetto/trace/android/packages_list.gen.h",
+ "external/perfetto/protos/perfetto/trace/android/pixel_modem_events.gen.h",
"external/perfetto/protos/perfetto/trace/android/protolog.gen.h",
"external/perfetto/protos/perfetto/trace/android/shell_transition.gen.h",
"external/perfetto/protos/perfetto/trace/android/surfaceflinger_common.gen.h",
@@ -5485,6 +5500,7 @@
"protos/perfetto/trace/android/initial_display_state.proto",
"protos/perfetto/trace/android/network_trace.proto",
"protos/perfetto/trace/android/packages_list.proto",
+ "protos/perfetto/trace/android/pixel_modem_events.proto",
"protos/perfetto/trace/android/protolog.proto",
"protos/perfetto/trace/android/shell_transition.proto",
"protos/perfetto/trace/android/surfaceflinger_common.proto",
@@ -5516,6 +5532,7 @@
"external/perfetto/protos/perfetto/trace/android/initial_display_state.pb.cc",
"external/perfetto/protos/perfetto/trace/android/network_trace.pb.cc",
"external/perfetto/protos/perfetto/trace/android/packages_list.pb.cc",
+ "external/perfetto/protos/perfetto/trace/android/pixel_modem_events.pb.cc",
"external/perfetto/protos/perfetto/trace/android/protolog.pb.cc",
"external/perfetto/protos/perfetto/trace/android/shell_transition.pb.cc",
"external/perfetto/protos/perfetto/trace/android/surfaceflinger_common.pb.cc",
@@ -5547,6 +5564,7 @@
"external/perfetto/protos/perfetto/trace/android/initial_display_state.pb.h",
"external/perfetto/protos/perfetto/trace/android/network_trace.pb.h",
"external/perfetto/protos/perfetto/trace/android/packages_list.pb.h",
+ "external/perfetto/protos/perfetto/trace/android/pixel_modem_events.pb.h",
"external/perfetto/protos/perfetto/trace/android/protolog.pb.h",
"external/perfetto/protos/perfetto/trace/android/shell_transition.pb.h",
"external/perfetto/protos/perfetto/trace/android/surfaceflinger_common.pb.h",
@@ -5611,6 +5629,7 @@
"protos/perfetto/trace/android/initial_display_state.proto",
"protos/perfetto/trace/android/network_trace.proto",
"protos/perfetto/trace/android/packages_list.proto",
+ "protos/perfetto/trace/android/pixel_modem_events.proto",
"protos/perfetto/trace/android/protolog.proto",
"protos/perfetto/trace/android/shell_transition.proto",
"protos/perfetto/trace/android/surfaceflinger_common.proto",
@@ -5643,6 +5662,7 @@
"external/perfetto/protos/perfetto/trace/android/initial_display_state.pbzero.cc",
"external/perfetto/protos/perfetto/trace/android/network_trace.pbzero.cc",
"external/perfetto/protos/perfetto/trace/android/packages_list.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/android/pixel_modem_events.pbzero.cc",
"external/perfetto/protos/perfetto/trace/android/protolog.pbzero.cc",
"external/perfetto/protos/perfetto/trace/android/shell_transition.pbzero.cc",
"external/perfetto/protos/perfetto/trace/android/surfaceflinger_common.pbzero.cc",
@@ -5675,6 +5695,7 @@
"external/perfetto/protos/perfetto/trace/android/initial_display_state.pbzero.h",
"external/perfetto/protos/perfetto/trace/android/network_trace.pbzero.h",
"external/perfetto/protos/perfetto/trace/android/packages_list.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/android/pixel_modem_events.pbzero.h",
"external/perfetto/protos/perfetto/trace/android/protolog.pbzero.h",
"external/perfetto/protos/perfetto/trace/android/shell_transition.pbzero.h",
"external/perfetto/protos/perfetto/trace/android/surfaceflinger_common.pbzero.h",
@@ -5882,6 +5903,7 @@
"protos/perfetto/config/android/android_system_property_config.proto",
"protos/perfetto/config/android/network_trace_config.proto",
"protos/perfetto/config/android/packages_list_config.proto",
+ "protos/perfetto/config/android/pixel_modem_config.proto",
"protos/perfetto/config/android/protolog_config.proto",
"protos/perfetto/config/android/surfaceflinger_layers_config.proto",
"protos/perfetto/config/android/surfaceflinger_transactions_config.proto",
@@ -5920,6 +5942,7 @@
"protos/perfetto/trace/android/initial_display_state.proto",
"protos/perfetto/trace/android/network_trace.proto",
"protos/perfetto/trace/android/packages_list.proto",
+ "protos/perfetto/trace/android/pixel_modem_events.proto",
"protos/perfetto/trace/android/protolog.proto",
"protos/perfetto/trace/android/shell_transition.proto",
"protos/perfetto/trace/android/surfaceflinger_common.proto",
@@ -11484,11 +11507,20 @@
filegroup {
name: "perfetto_src_trace_processor_importers_etw_full",
srcs: [
- "src/trace_processor/importers/etw/etw_module.cc",
+ "src/trace_processor/importers/etw/etw_module_impl.cc",
+ "src/trace_processor/importers/etw/etw_parser.cc",
"src/trace_processor/importers/etw/etw_tokenizer.cc",
],
}
+// GN: //src/trace_processor/importers/etw:minimal
+filegroup {
+ name: "perfetto_src_trace_processor_importers_etw_minimal",
+ srcs: [
+ "src/trace_processor/importers/etw/etw_module.cc",
+ ],
+}
+
// GN: //src/trace_processor/importers/ftrace:ftrace_descriptors
filegroup {
name: "perfetto_src_trace_processor_importers_ftrace_ftrace_descriptors",
@@ -12879,6 +12911,7 @@
"src/trace_redaction/scrub_process_stats.cc",
"src/trace_redaction/scrub_process_trees.cc",
"src/trace_redaction/scrub_trace_packet.cc",
+ "src/trace_redaction/suspend_resume.cc",
"src/trace_redaction/trace_redaction_framework.cc",
"src/trace_redaction/trace_redactor.cc",
],
@@ -12900,6 +12933,7 @@
"src/trace_redaction/redact_process_free_unittest.cc",
"src/trace_redaction/redact_sched_switch_unittest.cc",
"src/trace_redaction/redact_task_newtask_unittest.cc",
+ "src/trace_redaction/suspend_resume_unittest.cc",
],
}
@@ -13746,8 +13780,8 @@
}
// GN: [//protos/perfetto/trace:non_minimal_source_set, //protos/perfetto/trace:minimal_source_set]
-java_library {
- name: "perfetto_trace_java_protos",
+filegroup {
+ name: "perfetto_trace_filegroup_proto",
srcs: [
"protos/perfetto/common/android_energy_consumer_descriptor.proto",
"protos/perfetto/common/android_log_constants.proto",
@@ -13774,6 +13808,7 @@
"protos/perfetto/config/android/android_system_property_config.proto",
"protos/perfetto/config/android/network_trace_config.proto",
"protos/perfetto/config/android/packages_list_config.proto",
+ "protos/perfetto/config/android/pixel_modem_config.proto",
"protos/perfetto/config/android/protolog_config.proto",
"protos/perfetto/config/android/surfaceflinger_layers_config.proto",
"protos/perfetto/config/android/surfaceflinger_transactions_config.proto",
@@ -13812,6 +13847,225 @@
"protos/perfetto/trace/android/initial_display_state.proto",
"protos/perfetto/trace/android/network_trace.proto",
"protos/perfetto/trace/android/packages_list.proto",
+ "protos/perfetto/trace/android/pixel_modem_events.proto",
+ "protos/perfetto/trace/android/protolog.proto",
+ "protos/perfetto/trace/android/shell_transition.proto",
+ "protos/perfetto/trace/android/surfaceflinger_common.proto",
+ "protos/perfetto/trace/android/surfaceflinger_layers.proto",
+ "protos/perfetto/trace/android/surfaceflinger_transactions.proto",
+ "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_metadata.proto",
+ "protos/perfetto/trace/chrome/chrome_trace_event.proto",
+ "protos/perfetto/trace/chrome/chrome_trigger.proto",
+ "protos/perfetto/trace/chrome/v8.proto",
+ "protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/etw/etw.proto",
+ "protos/perfetto/trace/etw/etw_event.proto",
+ "protos/perfetto/trace/etw/etw_event_bundle.proto",
+ "protos/perfetto/trace/extension_descriptor.proto",
+ "protos/perfetto/trace/filesystem/inode_file_map.proto",
+ "protos/perfetto/trace/ftrace/android_fs.proto",
+ "protos/perfetto/trace/ftrace/binder.proto",
+ "protos/perfetto/trace/ftrace/block.proto",
+ "protos/perfetto/trace/ftrace/cgroup.proto",
+ "protos/perfetto/trace/ftrace/clk.proto",
+ "protos/perfetto/trace/ftrace/cma.proto",
+ "protos/perfetto/trace/ftrace/compaction.proto",
+ "protos/perfetto/trace/ftrace/cpuhp.proto",
+ "protos/perfetto/trace/ftrace/cros_ec.proto",
+ "protos/perfetto/trace/ftrace/dma_fence.proto",
+ "protos/perfetto/trace/ftrace/dmabuf_heap.proto",
+ "protos/perfetto/trace/ftrace/dpu.proto",
+ "protos/perfetto/trace/ftrace/drm.proto",
+ "protos/perfetto/trace/ftrace/ext4.proto",
+ "protos/perfetto/trace/ftrace/f2fs.proto",
+ "protos/perfetto/trace/ftrace/fastrpc.proto",
+ "protos/perfetto/trace/ftrace/fence.proto",
+ "protos/perfetto/trace/ftrace/filemap.proto",
+ "protos/perfetto/trace/ftrace/ftrace.proto",
+ "protos/perfetto/trace/ftrace/ftrace_event.proto",
+ "protos/perfetto/trace/ftrace/ftrace_event_bundle.proto",
+ "protos/perfetto/trace/ftrace/ftrace_stats.proto",
+ "protos/perfetto/trace/ftrace/g2d.proto",
+ "protos/perfetto/trace/ftrace/generic.proto",
+ "protos/perfetto/trace/ftrace/gpu_mem.proto",
+ "protos/perfetto/trace/ftrace/gpu_scheduler.proto",
+ "protos/perfetto/trace/ftrace/hyp.proto",
+ "protos/perfetto/trace/ftrace/i2c.proto",
+ "protos/perfetto/trace/ftrace/ion.proto",
+ "protos/perfetto/trace/ftrace/ipi.proto",
+ "protos/perfetto/trace/ftrace/irq.proto",
+ "protos/perfetto/trace/ftrace/kmem.proto",
+ "protos/perfetto/trace/ftrace/kvm.proto",
+ "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
+ "protos/perfetto/trace/ftrace/lwis.proto",
+ "protos/perfetto/trace/ftrace/mali.proto",
+ "protos/perfetto/trace/ftrace/mdss.proto",
+ "protos/perfetto/trace/ftrace/mm_event.proto",
+ "protos/perfetto/trace/ftrace/net.proto",
+ "protos/perfetto/trace/ftrace/oom.proto",
+ "protos/perfetto/trace/ftrace/panel.proto",
+ "protos/perfetto/trace/ftrace/perf_trace_counters.proto",
+ "protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/printk.proto",
+ "protos/perfetto/trace/ftrace/raw_syscalls.proto",
+ "protos/perfetto/trace/ftrace/regulator.proto",
+ "protos/perfetto/trace/ftrace/rpm.proto",
+ "protos/perfetto/trace/ftrace/samsung.proto",
+ "protos/perfetto/trace/ftrace/sched.proto",
+ "protos/perfetto/trace/ftrace/scm.proto",
+ "protos/perfetto/trace/ftrace/sde.proto",
+ "protos/perfetto/trace/ftrace/signal.proto",
+ "protos/perfetto/trace/ftrace/skb.proto",
+ "protos/perfetto/trace/ftrace/sock.proto",
+ "protos/perfetto/trace/ftrace/sync.proto",
+ "protos/perfetto/trace/ftrace/synthetic.proto",
+ "protos/perfetto/trace/ftrace/systrace.proto",
+ "protos/perfetto/trace/ftrace/task.proto",
+ "protos/perfetto/trace/ftrace/tcp.proto",
+ "protos/perfetto/trace/ftrace/test_bundle_wrapper.proto",
+ "protos/perfetto/trace/ftrace/thermal.proto",
+ "protos/perfetto/trace/ftrace/trusty.proto",
+ "protos/perfetto/trace/ftrace/ufs.proto",
+ "protos/perfetto/trace/ftrace/v4l2.proto",
+ "protos/perfetto/trace/ftrace/virtio_gpu.proto",
+ "protos/perfetto/trace/ftrace/virtio_video.proto",
+ "protos/perfetto/trace/ftrace/vmscan.proto",
+ "protos/perfetto/trace/ftrace/workqueue.proto",
+ "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+ "protos/perfetto/trace/gpu/gpu_log.proto",
+ "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_api_event.proto",
+ "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
+ "protos/perfetto/trace/interned_data/interned_data.proto",
+ "protos/perfetto/trace/memory_graph.proto",
+ "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
+ "protos/perfetto/trace/perfetto/tracing_service_event.proto",
+ "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto",
+ "protos/perfetto/trace/power/android_entity_state_residency.proto",
+ "protos/perfetto/trace/power/battery_counters.proto",
+ "protos/perfetto/trace/power/power_rails.proto",
+ "protos/perfetto/trace/profiling/deobfuscation.proto",
+ "protos/perfetto/trace/profiling/heap_graph.proto",
+ "protos/perfetto/trace/profiling/profile_common.proto",
+ "protos/perfetto/trace/profiling/profile_packet.proto",
+ "protos/perfetto/trace/profiling/smaps.proto",
+ "protos/perfetto/trace/ps/process_stats.proto",
+ "protos/perfetto/trace/ps/process_tree.proto",
+ "protos/perfetto/trace/remote_clock_sync.proto",
+ "protos/perfetto/trace/statsd/statsd_atom.proto",
+ "protos/perfetto/trace/sys_stats/sys_stats.proto",
+ "protos/perfetto/trace/system_info.proto",
+ "protos/perfetto/trace/system_info/cpu_info.proto",
+ "protos/perfetto/trace/test_event.proto",
+ "protos/perfetto/trace/test_extensions.proto",
+ "protos/perfetto/trace/trace.proto",
+ "protos/perfetto/trace/trace_packet.proto",
+ "protos/perfetto/trace/trace_packet_defaults.proto",
+ "protos/perfetto/trace/trace_uuid.proto",
+ "protos/perfetto/trace/track_event/chrome_active_processes.proto",
+ "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
+ "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
+ "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
+ "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
+ "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
+ "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
+ "protos/perfetto/trace/track_event/chrome_latency_info.proto",
+ "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+ "protos/perfetto/trace/track_event/chrome_message_pump.proto",
+ "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
+ "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
+ "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
+ "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
+ "protos/perfetto/trace/track_event/chrome_user_event.proto",
+ "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
+ "protos/perfetto/trace/track_event/counter_descriptor.proto",
+ "protos/perfetto/trace/track_event/debug_annotation.proto",
+ "protos/perfetto/trace/track_event/log_message.proto",
+ "protos/perfetto/trace/track_event/pixel_modem.proto",
+ "protos/perfetto/trace/track_event/process_descriptor.proto",
+ "protos/perfetto/trace/track_event/range_of_interest.proto",
+ "protos/perfetto/trace/track_event/screenshot.proto",
+ "protos/perfetto/trace/track_event/source_location.proto",
+ "protos/perfetto/trace/track_event/task_execution.proto",
+ "protos/perfetto/trace/track_event/thread_descriptor.proto",
+ "protos/perfetto/trace/track_event/track_descriptor.proto",
+ "protos/perfetto/trace/track_event/track_event.proto",
+ "protos/perfetto/trace/translation/translation_table.proto",
+ "protos/perfetto/trace/trigger.proto",
+ "protos/perfetto/trace/ui_state.proto",
+ ],
+}
+
+// GN: [//protos/perfetto/trace:non_minimal_source_set, //protos/perfetto/trace:minimal_source_set]
+java_library {
+ name: "perfetto_trace_java_protos",
+ srcs: [
+ "protos/perfetto/common/android_energy_consumer_descriptor.proto",
+ "protos/perfetto/common/android_log_constants.proto",
+ "protos/perfetto/common/builtin_clock.proto",
+ "protos/perfetto/common/commit_data_request.proto",
+ "protos/perfetto/common/data_source_descriptor.proto",
+ "protos/perfetto/common/descriptor.proto",
+ "protos/perfetto/common/ftrace_descriptor.proto",
+ "protos/perfetto/common/gpu_counter_descriptor.proto",
+ "protos/perfetto/common/interceptor_descriptor.proto",
+ "protos/perfetto/common/observable_events.proto",
+ "protos/perfetto/common/perf_events.proto",
+ "protos/perfetto/common/protolog_common.proto",
+ "protos/perfetto/common/sys_stats_counters.proto",
+ "protos/perfetto/common/trace_stats.proto",
+ "protos/perfetto/common/tracing_service_capabilities.proto",
+ "protos/perfetto/common/tracing_service_state.proto",
+ "protos/perfetto/common/track_event_descriptor.proto",
+ "protos/perfetto/config/android/android_game_intervention_list_config.proto",
+ "protos/perfetto/config/android/android_input_event_config.proto",
+ "protos/perfetto/config/android/android_log_config.proto",
+ "protos/perfetto/config/android/android_polled_state_config.proto",
+ "protos/perfetto/config/android/android_sdk_sysprop_guard_config.proto",
+ "protos/perfetto/config/android/android_system_property_config.proto",
+ "protos/perfetto/config/android/network_trace_config.proto",
+ "protos/perfetto/config/android/packages_list_config.proto",
+ "protos/perfetto/config/android/pixel_modem_config.proto",
+ "protos/perfetto/config/android/protolog_config.proto",
+ "protos/perfetto/config/android/surfaceflinger_layers_config.proto",
+ "protos/perfetto/config/android/surfaceflinger_transactions_config.proto",
+ "protos/perfetto/config/chrome/chrome_config.proto",
+ "protos/perfetto/config/chrome/scenario_config.proto",
+ "protos/perfetto/config/chrome/v8_config.proto",
+ "protos/perfetto/config/data_source_config.proto",
+ "protos/perfetto/config/etw/etw_config.proto",
+ "protos/perfetto/config/ftrace/ftrace_config.proto",
+ "protos/perfetto/config/gpu/gpu_counter_config.proto",
+ "protos/perfetto/config/gpu/vulkan_memory_config.proto",
+ "protos/perfetto/config/inode_file/inode_file_config.proto",
+ "protos/perfetto/config/interceptor_config.proto",
+ "protos/perfetto/config/interceptors/console_config.proto",
+ "protos/perfetto/config/power/android_power_config.proto",
+ "protos/perfetto/config/process_stats/process_stats_config.proto",
+ "protos/perfetto/config/profiling/heapprofd_config.proto",
+ "protos/perfetto/config/profiling/java_hprof_config.proto",
+ "protos/perfetto/config/profiling/perf_event_config.proto",
+ "protos/perfetto/config/statsd/atom_ids.proto",
+ "protos/perfetto/config/statsd/statsd_tracing_config.proto",
+ "protos/perfetto/config/stress_test_config.proto",
+ "protos/perfetto/config/sys_stats/sys_stats_config.proto",
+ "protos/perfetto/config/system_info/system_info.proto",
+ "protos/perfetto/config/test_config.proto",
+ "protos/perfetto/config/trace_config.proto",
+ "protos/perfetto/config/track_event/track_event_config.proto",
+ "protos/perfetto/trace/android/android_game_intervention_list.proto",
+ "protos/perfetto/trace/android/android_input_event.proto",
+ "protos/perfetto/trace/android/android_log.proto",
+ "protos/perfetto/trace/android/android_system_property.proto",
+ "protos/perfetto/trace/android/camera_event.proto",
+ "protos/perfetto/trace/android/frame_timeline_event.proto",
+ "protos/perfetto/trace/android/gpu_mem_event.proto",
+ "protos/perfetto/trace/android/graphics_frame_event.proto",
+ "protos/perfetto/trace/android/initial_display_state.proto",
+ "protos/perfetto/trace/android/network_trace.proto",
+ "protos/perfetto/trace/android/packages_list.proto",
+ "protos/perfetto/trace/android/pixel_modem_events.proto",
"protos/perfetto/trace/android/protolog.proto",
"protos/perfetto/trace/android/shell_transition.proto",
"protos/perfetto/trace/android/surfaceflinger_common.proto",
@@ -14322,6 +14576,7 @@
":perfetto_src_trace_processor_importers_common_trace_parser_hdr",
":perfetto_src_trace_processor_importers_common_unittests",
":perfetto_src_trace_processor_importers_etw_full",
+ ":perfetto_src_trace_processor_importers_etw_minimal",
":perfetto_src_trace_processor_importers_ftrace_ftrace_descriptors",
":perfetto_src_trace_processor_importers_ftrace_full",
":perfetto_src_trace_processor_importers_ftrace_minimal",
@@ -15049,6 +15304,7 @@
":perfetto_src_trace_processor_importers_common_parser_types",
":perfetto_src_trace_processor_importers_common_trace_parser_hdr",
":perfetto_src_trace_processor_importers_etw_full",
+ ":perfetto_src_trace_processor_importers_etw_minimal",
":perfetto_src_trace_processor_importers_ftrace_ftrace_descriptors",
":perfetto_src_trace_processor_importers_ftrace_full",
":perfetto_src_trace_processor_importers_ftrace_minimal",
@@ -15269,6 +15525,7 @@
":perfetto_src_trace_processor_importers_common_common",
":perfetto_src_trace_processor_importers_common_parser_types",
":perfetto_src_trace_processor_importers_common_trace_parser_hdr",
+ ":perfetto_src_trace_processor_importers_etw_minimal",
":perfetto_src_trace_processor_importers_ftrace_minimal",
":perfetto_src_trace_processor_importers_fuchsia_fuchsia_record",
":perfetto_src_trace_processor_importers_json_minimal",
@@ -15421,6 +15678,7 @@
":perfetto_src_trace_processor_importers_common_parser_types",
":perfetto_src_trace_processor_importers_common_trace_parser_hdr",
":perfetto_src_trace_processor_importers_etw_full",
+ ":perfetto_src_trace_processor_importers_etw_minimal",
":perfetto_src_trace_processor_importers_ftrace_ftrace_descriptors",
":perfetto_src_trace_processor_importers_ftrace_full",
":perfetto_src_trace_processor_importers_ftrace_minimal",
@@ -16107,11 +16365,10 @@
],
}
-// TODO(b/315118713): use list of proto file sources instead of merged proto
gensrcs {
name: "perfetto_trace_javastream_protos",
srcs: [
- "protos/perfetto/trace/perfetto_trace.proto",
+ ":perfetto_trace_filegroup_proto",
],
tools: [
"aprotoc",
diff --git a/Android.bp.extras b/Android.bp.extras
index 3aab5af..3ebf51e 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -172,11 +172,10 @@
],
}
-// TODO(b/315118713): use list of proto file sources instead of merged proto
gensrcs {
name: "perfetto_trace_javastream_protos",
srcs: [
- "protos/perfetto/trace/perfetto_trace.proto",
+ ":perfetto_trace_filegroup_proto",
],
tools: [
"aprotoc",
diff --git a/BUILD b/BUILD
index 4e316ed..12fe725 100644
--- a/BUILD
+++ b/BUILD
@@ -225,6 +225,7 @@
":src_trace_processor_importers_common_parser_types",
":src_trace_processor_importers_common_trace_parser_hdr",
":src_trace_processor_importers_etw_full",
+ ":src_trace_processor_importers_etw_minimal",
":src_trace_processor_importers_ftrace_ftrace_descriptors",
":src_trace_processor_importers_ftrace_full",
":src_trace_processor_importers_ftrace_minimal",
@@ -1526,13 +1527,24 @@
perfetto_filegroup(
name = "src_trace_processor_importers_etw_full",
srcs = [
- "src/trace_processor/importers/etw/etw_module.cc",
- "src/trace_processor/importers/etw/etw_module.h",
+ "src/trace_processor/importers/etw/etw_module_impl.cc",
+ "src/trace_processor/importers/etw/etw_module_impl.h",
+ "src/trace_processor/importers/etw/etw_parser.cc",
+ "src/trace_processor/importers/etw/etw_parser.h",
"src/trace_processor/importers/etw/etw_tokenizer.cc",
"src/trace_processor/importers/etw/etw_tokenizer.h",
],
)
+# GN target: //src/trace_processor/importers/etw:minimal
+perfetto_filegroup(
+ name = "src_trace_processor_importers_etw_minimal",
+ srcs = [
+ "src/trace_processor/importers/etw/etw_module.cc",
+ "src/trace_processor/importers/etw/etw_module.h",
+ ],
+)
+
# GN target: //src/trace_processor/importers/ftrace:ftrace_descriptors
perfetto_filegroup(
name = "src_trace_processor_importers_ftrace_ftrace_descriptors",
@@ -3881,6 +3893,7 @@
"protos/perfetto/config/android/android_system_property_config.proto",
"protos/perfetto/config/android/network_trace_config.proto",
"protos/perfetto/config/android/packages_list_config.proto",
+ "protos/perfetto/config/android/pixel_modem_config.proto",
"protos/perfetto/config/android/protolog_config.proto",
"protos/perfetto/config/android/surfaceflinger_layers_config.proto",
"protos/perfetto/config/android/surfaceflinger_transactions_config.proto",
@@ -4592,6 +4605,7 @@
"protos/perfetto/trace/android/initial_display_state.proto",
"protos/perfetto/trace/android/network_trace.proto",
"protos/perfetto/trace/android/packages_list.proto",
+ "protos/perfetto/trace/android/pixel_modem_events.proto",
"protos/perfetto/trace/android/protolog.proto",
"protos/perfetto/trace/android/shell_transition.proto",
"protos/perfetto/trace/android/surfaceflinger_common.proto",
@@ -5708,6 +5722,7 @@
":src_trace_processor_importers_common_parser_types",
":src_trace_processor_importers_common_trace_parser_hdr",
":src_trace_processor_importers_etw_full",
+ ":src_trace_processor_importers_etw_minimal",
":src_trace_processor_importers_ftrace_ftrace_descriptors",
":src_trace_processor_importers_ftrace_full",
":src_trace_processor_importers_ftrace_minimal",
@@ -5877,6 +5892,7 @@
":src_trace_processor_importers_common_parser_types",
":src_trace_processor_importers_common_trace_parser_hdr",
":src_trace_processor_importers_etw_full",
+ ":src_trace_processor_importers_etw_minimal",
":src_trace_processor_importers_ftrace_ftrace_descriptors",
":src_trace_processor_importers_ftrace_full",
":src_trace_processor_importers_ftrace_minimal",
@@ -6104,6 +6120,7 @@
":src_trace_processor_importers_common_parser_types",
":src_trace_processor_importers_common_trace_parser_hdr",
":src_trace_processor_importers_etw_full",
+ ":src_trace_processor_importers_etw_minimal",
":src_trace_processor_importers_ftrace_ftrace_descriptors",
":src_trace_processor_importers_ftrace_full",
":src_trace_processor_importers_ftrace_minimal",
diff --git a/OWNERS b/OWNERS
index 3c29a20..b2a1331 100644
--- a/OWNERS
+++ b/OWNERS
@@ -7,7 +7,6 @@
skyostil@google.com
# UI, Ftrace interop, traced_probes, protozero, Android internals.
-hjd@google.com
# Trace Processor, metrics, infra.
lalitm@google.com
diff --git a/bazel/proto_gen.bzl b/bazel/proto_gen.bzl
index cd31d44..c5fd127 100644
--- a/bazel/proto_gen.bzl
+++ b/bazel/proto_gen.bzl
@@ -26,6 +26,11 @@
for dep in ctx.attr.deps
for f in dep[ProtoInfo].transitive_imports.to_list()
]
+ proto_paths = [
+ f
+ for dep in ctx.attr.deps
+ for f in dep[ProtoInfo].transitive_proto_path.to_list()
+ ]
proto_path = "."
@@ -58,8 +63,10 @@
out_files += [ctx.actions.declare_file(base_path + ".%s.cc" % suffix)]
arguments = [
- "--proto_path=" + proto_path,
+ "--proto_path=" + proto_path
+ for proto_path in proto_paths
]
+
plugin_deps = []
if ctx.attr.plugin:
wrap_arg = ctx.attr.wrapper_namespace
diff --git a/docs/contributing/build-instructions.md b/docs/contributing/build-instructions.md
index c192898..85025d6 100644
--- a/docs/contributing/build-instructions.md
+++ b/docs/contributing/build-instructions.md
@@ -535,6 +535,7 @@
"./ui",
],
"prettier.configPath": "ui/.prettierrc.yml",
+ "typescript.preferences.importModuleSpecifier": "relative",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
diff --git a/docs/data-sources/java-heap-profiler.md b/docs/data-sources/java-heap-profiler.md
index 01af1f5..4056436 100644
--- a/docs/data-sources/java-heap-profiler.md
+++ b/docs/data-sources/java-heap-profiler.md
@@ -68,9 +68,9 @@
select distinct graph_sample_ts, upid from heap_graph_object
```
-graph_sample_ts | upid |
---------------------|--------------------|
- 56785646801 | 1 |
+|graph_sample_ts | upid |
+|--------------------|--------------------|
+| 56785646801 | 1 |
We can then use them to get the flamegraph data.
diff --git a/infra/OWNERS b/infra/OWNERS
index a4b3fef..0178ed0 100644
--- a/infra/OWNERS
+++ b/infra/OWNERS
@@ -1,3 +1,2 @@
-hjd@google.com
lalitm@google.com
primiano@google.com
diff --git a/protos/perfetto/config/android/BUILD.gn b/protos/perfetto/config/android/BUILD.gn
index 0af8024..ec4f7ce 100644
--- a/protos/perfetto/config/android/BUILD.gn
+++ b/protos/perfetto/config/android/BUILD.gn
@@ -26,6 +26,7 @@
"android_system_property_config.proto",
"network_trace_config.proto",
"packages_list_config.proto",
+ "pixel_modem_config.proto",
"protolog_config.proto",
"surfaceflinger_layers_config.proto",
"surfaceflinger_transactions_config.proto",
diff --git a/protos/perfetto/config/android/pixel_modem_config.proto b/protos/perfetto/config/android/pixel_modem_config.proto
new file mode 100644
index 0000000..d3efc59
--- /dev/null
+++ b/protos/perfetto/config/android/pixel_modem_config.proto
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+// Data source that records events from the modem.
+message PixelModemConfig {
+ // Event group to record, as defined by the modem.
+ enum EventGroup {
+ EVENT_GROUP_UNKNOWN = 0;
+
+ // Events suitable for low bandwidth tracing only.
+ EVENT_GROUP_LOW_BANDWIDTH = 1;
+
+ // Events suitable for high and low bandwidth tracing.
+ EVENT_GROUP_HIGH_AND_LOW_BANDWIDTH = 2;
+ }
+
+ optional EventGroup event_group = 1;
+
+ // If set, record only events with these hashes.
+ repeated int64 pigweed_hash_allow_list = 2;
+
+ // If set and allow_list is not set, deny events with these hashes.
+ repeated int64 pigweed_hash_deny_list = 3;
+}
diff --git a/protos/perfetto/config/data_source_config.proto b/protos/perfetto/config/data_source_config.proto
index e9a2594..3b8e860 100644
--- a/protos/perfetto/config/data_source_config.proto
+++ b/protos/perfetto/config/data_source_config.proto
@@ -26,6 +26,7 @@
import "protos/perfetto/config/android/android_sdk_sysprop_guard_config.proto";
import "protos/perfetto/config/android/network_trace_config.proto";
import "protos/perfetto/config/android/packages_list_config.proto";
+import "protos/perfetto/config/android/pixel_modem_config.proto";
import "protos/perfetto/config/android/protolog_config.proto";
import "protos/perfetto/config/android/surfaceflinger_layers_config.proto";
import "protos/perfetto/config/android/surfaceflinger_transactions_config.proto";
@@ -49,7 +50,7 @@
import "protos/perfetto/config/system_info/system_info.proto";
// The configuration that is passed to each data source when starting tracing.
-// Next id: 129
+// Next id: 130
message DataSourceConfig {
enum SessionInitiator {
SESSION_INITIATOR_UNSPECIFIED = 0;
@@ -197,6 +198,9 @@
// Data source name: android.input.inputevent
optional AndroidInputEventConfig android_input_event_config = 128 [lazy = true];
+ // Data source name: android.pixel.modem
+ optional PixelModemConfig pixel_modem_config = 129 [lazy = true];
+
// This is a fallback mechanism to send a free-form text config to the
// producer. In theory this should never be needed. All the code that
// is part of the platform (i.e. traced service) is supposed to *not* truncate
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 2fd3c55..7777d1c 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -660,6 +660,32 @@
// End of protos/perfetto/config/android/packages_list_config.proto
+// Begin of protos/perfetto/config/android/pixel_modem_config.proto
+
+// Data source that records events from the modem.
+message PixelModemConfig {
+ // Event group to record, as defined by the modem.
+ enum EventGroup {
+ EVENT_GROUP_UNKNOWN = 0;
+
+ // Events suitable for low bandwidth tracing only.
+ EVENT_GROUP_LOW_BANDWIDTH = 1;
+
+ // Events suitable for high and low bandwidth tracing.
+ EVENT_GROUP_HIGH_AND_LOW_BANDWIDTH = 2;
+ }
+
+ optional EventGroup event_group = 1;
+
+ // If set, record only events with these hashes.
+ repeated int64 pigweed_hash_allow_list = 2;
+
+ // If set and allow_list is not set, deny events with these hashes.
+ repeated int64 pigweed_hash_deny_list = 3;
+}
+
+// End of protos/perfetto/config/android/pixel_modem_config.proto
+
// Begin of protos/perfetto/common/protolog_common.proto
enum ProtoLogLevel {
@@ -3231,7 +3257,7 @@
// Begin of protos/perfetto/config/data_source_config.proto
// The configuration that is passed to each data source when starting tracing.
-// Next id: 129
+// Next id: 130
message DataSourceConfig {
enum SessionInitiator {
SESSION_INITIATOR_UNSPECIFIED = 0;
@@ -3379,6 +3405,9 @@
// Data source name: android.input.inputevent
optional AndroidInputEventConfig android_input_event_config = 128 [lazy = true];
+ // Data source name: android.pixel.modem
+ optional PixelModemConfig pixel_modem_config = 129 [lazy = true];
+
// This is a fallback mechanism to send a free-form text config to the
// producer. In theory this should never be needed. All the code that
// is part of the platform (i.e. traced service) is supposed to *not* truncate
diff --git a/protos/perfetto/ipc/OWNERS b/protos/perfetto/ipc/OWNERS
index a10c8b8..bead02d 100644
--- a/protos/perfetto/ipc/OWNERS
+++ b/protos/perfetto/ipc/OWNERS
@@ -4,6 +4,5 @@
set noparent
eseckler@google.com
-hjd@google.com
primiano@google.com
skyostil@google.com
diff --git a/protos/perfetto/trace/android/BUILD.gn b/protos/perfetto/trace/android/BUILD.gn
index c88ca28..1910078 100644
--- a/protos/perfetto/trace/android/BUILD.gn
+++ b/protos/perfetto/trace/android/BUILD.gn
@@ -29,6 +29,7 @@
"initial_display_state.proto",
"network_trace.proto",
"packages_list.proto",
+ "pixel_modem_events.proto",
"protolog.proto",
"shell_transition.proto",
"surfaceflinger_common.proto",
diff --git a/protos/perfetto/trace/android/pixel_modem_events.proto b/protos/perfetto/trace/android/pixel_modem_events.proto
new file mode 100644
index 0000000..f014311
--- /dev/null
+++ b/protos/perfetto/trace/android/pixel_modem_events.proto
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+message PixelModemEvents {
+ // Pigweed-format dehydrated events.
+ repeated bytes events = 1;
+
+ // Timestamps of the events, converted to CLOCK_BOOTTIME. The first
+ // timestamp is the absolute timestamp of the first event. Subsequent
+ // timestamps are deltas from the previous timestamp.
+ // The nth entry from `events` gets the nth entry here.
+ repeated uint64 event_time_nanos = 2;
+}
+
+// NB: this is not emitted in the trace but can be prepended later.
+message PixelModemTokenDatabase {
+ // Pigweed-format database to allow event rehydration.
+ optional bytes database = 1;
+}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index f949e69..81977bf 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -660,6 +660,32 @@
// End of protos/perfetto/config/android/packages_list_config.proto
+// Begin of protos/perfetto/config/android/pixel_modem_config.proto
+
+// Data source that records events from the modem.
+message PixelModemConfig {
+ // Event group to record, as defined by the modem.
+ enum EventGroup {
+ EVENT_GROUP_UNKNOWN = 0;
+
+ // Events suitable for low bandwidth tracing only.
+ EVENT_GROUP_LOW_BANDWIDTH = 1;
+
+ // Events suitable for high and low bandwidth tracing.
+ EVENT_GROUP_HIGH_AND_LOW_BANDWIDTH = 2;
+ }
+
+ optional EventGroup event_group = 1;
+
+ // If set, record only events with these hashes.
+ repeated int64 pigweed_hash_allow_list = 2;
+
+ // If set and allow_list is not set, deny events with these hashes.
+ repeated int64 pigweed_hash_deny_list = 3;
+}
+
+// End of protos/perfetto/config/android/pixel_modem_config.proto
+
// Begin of protos/perfetto/common/protolog_common.proto
enum ProtoLogLevel {
@@ -3231,7 +3257,7 @@
// Begin of protos/perfetto/config/data_source_config.proto
// The configuration that is passed to each data source when starting tracing.
-// Next id: 129
+// Next id: 130
message DataSourceConfig {
enum SessionInitiator {
SESSION_INITIATOR_UNSPECIFIED = 0;
@@ -3379,6 +3405,9 @@
// Data source name: android.input.inputevent
optional AndroidInputEventConfig android_input_event_config = 128 [lazy = true];
+ // Data source name: android.pixel.modem
+ optional PixelModemConfig pixel_modem_config = 129 [lazy = true];
+
// This is a fallback mechanism to send a free-form text config to the
// producer. In theory this should never be needed. All the code that
// is part of the platform (i.e. traced service) is supposed to *not* truncate
@@ -4996,6 +5025,27 @@
// End of protos/perfetto/trace/android/packages_list.proto
+// Begin of protos/perfetto/trace/android/pixel_modem_events.proto
+
+message PixelModemEvents {
+ // Pigweed-format dehydrated events.
+ repeated bytes events = 1;
+
+ // Timestamps of the events, converted to CLOCK_BOOTTIME. The first
+ // timestamp is the absolute timestamp of the first event. Subsequent
+ // timestamps are deltas from the previous timestamp.
+ // The nth entry from `events` gets the nth entry here.
+ repeated uint64 event_time_nanos = 2;
+}
+
+// NB: this is not emitted in the trace but can be prepended later.
+message PixelModemTokenDatabase {
+ // Pigweed-format database to allow event rehydration.
+ optional bytes database = 1;
+}
+
+// End of protos/perfetto/trace/android/pixel_modem_events.proto
+
// Begin of protos/perfetto/trace/android/protolog.proto
/* represents a single log entry */
@@ -14721,7 +14771,7 @@
// See the [Buffers and Dataflow](/docs/concepts/buffers.md) doc for details.
//
// Next reserved id: 14 (up to 15).
-// Next id: 109.
+// Next id: 112.
message TracePacket {
// The timestamp of the TracePacket.
// By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -14861,6 +14911,9 @@
// Clock synchronization with remote machines.
RemoteClockSync remote_clock_sync = 107;
+ PixelModemEvents pixel_modem_events = 110;
+ PixelModemTokenDatabase pixel_modem_token_database = 111;
+
// This field is only used for testing.
// In previous versions of this proto this field had the id 268435455
// This caused many problems:
diff --git a/protos/perfetto/trace/trace_packet.proto b/protos/perfetto/trace/trace_packet.proto
index 93fb7d3..62d7e6f 100644
--- a/protos/perfetto/trace/trace_packet.proto
+++ b/protos/perfetto/trace/trace_packet.proto
@@ -30,6 +30,7 @@
import "protos/perfetto/trace/android/initial_display_state.proto";
import "protos/perfetto/trace/android/network_trace.proto";
import "protos/perfetto/trace/android/packages_list.proto";
+import "protos/perfetto/trace/android/pixel_modem_events.proto";
import "protos/perfetto/trace/android/protolog.proto";
import "protos/perfetto/trace/android/shell_transition.proto";
import "protos/perfetto/trace/android/surfaceflinger_layers.proto";
@@ -103,7 +104,7 @@
// See the [Buffers and Dataflow](/docs/concepts/buffers.md) doc for details.
//
// Next reserved id: 14 (up to 15).
-// Next id: 109.
+// Next id: 112.
message TracePacket {
// The timestamp of the TracePacket.
// By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -243,6 +244,9 @@
// Clock synchronization with remote machines.
RemoteClockSync remote_clock_sync = 107;
+ PixelModemEvents pixel_modem_events = 110;
+ PixelModemTokenDatabase pixel_modem_token_database = 111;
+
// This field is only used for testing.
// In previous versions of this proto this field had the id 268435455
// This caused many problems:
diff --git a/protos/third_party/chromium/chrome_track_event.proto b/protos/third_party/chromium/chrome_track_event.proto
index 882d6ff..bea5d6e 100644
--- a/protos/third_party/chromium/chrome_track_event.proto
+++ b/protos/third_party/chromium/chrome_track_event.proto
@@ -596,7 +596,7 @@
optional ShutdownBehavior shutdown_behavior = 4;
}
-// TODO(crbug.com/1258495): Add more information.
+// TODO(crbug.com/40797026): Add more information.
message BackForwardCacheCanStoreDocumentResult {
enum BackForwardCacheNotRestoredReason {
NOT_MAIN_FRAME = 1;
@@ -722,7 +722,7 @@
TASK_TYPE_WORKER_THREAD_TASK_QUEUE_COMPOSITOR = 48;
TASK_TYPE_COMPOSITOR_THREAD_TASK_QUEUE_INPUT = 49;
- // TODO(crbug.com/860545): Obsolete. Remove.
+ // TODO(crbug.com/40583778): Obsolete. Remove.
TASK_TYPE_NETWORKING_WITH_URL_LOADER_ANNOTATION = 50;
TASK_TYPE_WORKER_ANIMATION = 51;
@@ -1835,9 +1835,27 @@
optional int64 draw_estimate_delta_us = 7;
}
+message WebViewStartup {
+ optional bool from_ui_thread = 1;
+ // This enum must be kept in sync with WebViewChromiumAwInit.CallSite
+ enum CallSite {
+ GET_AW_TRACING_CONTROLLER = 0;
+ GET_AW_PROXY_CONTROLLER = 1;
+ WEBVIEW_INSTANCE = 2;
+ GET_STATICS = 3;
+ GET_DEFAULT_GEOLOCATION_PERMISSIONS = 4;
+ GET_DEFAULT_SERVICE_WORKER_CONTROLLER = 5;
+ GET_WEB_ICON_DATABASE = 6;
+ GET_DEFAULT_WEB_STORAGE = 7;
+ GET_DEFAULT_WEBVIEW_DATABASE = 8;
+ GET_TRACING_CONTROLLER = 9;
+ }
+ optional CallSite call_site = 2;
+}
+
message ChromeTrackEvent {
// Extension range for Chrome: 1000-1999
- // Next ID: 1063
+ // Next ID: 1064
extend TrackEvent {
optional ChromeAppState chrome_app_state = 1000;
@@ -1970,5 +1988,7 @@
optional ViewClassName view_class_name = 1061;
optional ChromeCompositorSchedulerStateV2 cc_scheduler_state = 1062;
+
+ optional WebViewStartup webview_startup = 1063;
}
}
diff --git a/python/perfetto/trace_uri_resolver/resolver.py b/python/perfetto/trace_uri_resolver/resolver.py
index bcdbf93..32f224d 100644
--- a/python/perfetto/trace_uri_resolver/resolver.py
+++ b/python/perfetto/trace_uri_resolver/resolver.py
@@ -190,11 +190,13 @@
"""Creates an the args dictionary from a trace URI.
URIs have the form:
- android_ci:day=2021-01-01;devices=blueline,crosshatch;key>=value
+ android_ci:day=2021-01-01;devices=blueline,crosshatch;key>=value;\
+ version>=1;version<5
This is converted to a dictionary of the form:
{'day': '2021-01-01', 'id': ['blueline', 'crosshatch'],
- 'key': ConstraintClass('value', Op.GE)}
+ 'key': ConstraintClass('value', Op.GE),
+ 'version': [ConstraintClass(1, Op.GE), ConstraintClass(5, Op.LT)]}
"""
_, args_str = util.parse_trace_uri(uri)
if not args_str:
@@ -206,13 +208,14 @@
(key, op, value) = _parse_arg(arg)
lst = value.split(',')
if len(lst) > 1:
- args_dict[key] = lst
+ args_dict_value = lst
else:
- args_dict[key] = value
+ args_dict_value = value
if key not in type_hints:
if op != ConstraintClass.Op.EQ:
raise ValueError(f'{key} only supports "=" operator')
+ args_dict[key] = args_dict_value
continue
have_constraint = False
type_hint = type_hints[key]
@@ -227,5 +230,12 @@
raise ValueError('Operator other than "=" passed to argument which '
'does not have constraint type: ' + arg)
if have_constraint:
- args_dict[key] = ConstraintClass(args_dict[key], op)
+ if key not in args_dict:
+ args_dict[key] = ConstraintClass(args_dict_value, op)
+ else:
+ if isinstance(args_dict[key], ConstraintClass):
+ args_dict[key] = [args_dict[key]]
+ args_dict[key].append(ConstraintClass(args_dict_value, op))
+ else:
+ args_dict[key] = args_dict_value
return args_dict
diff --git a/python/test/resolver_unittest.py b/python/test/resolver_unittest.py
index 5cdb9f9..5ac9f63 100644
--- a/python/test/resolver_unittest.py
+++ b/python/test/resolver_unittest.py
@@ -197,6 +197,22 @@
self.assertEqual(
_args_dict_from_uri('foo:key<v1', type_hints),
{'key': ConstraintClass('v1', ConstraintClass.Op.LT)})
+ self.assertEqual(
+ _args_dict_from_uri('foo:key>v1;key<=v2', type_hints), {
+ 'key': [
+ ConstraintClass('v1', ConstraintClass.Op.GT),
+ ConstraintClass('v2', ConstraintClass.Op.LE)
+ ]
+ })
+ self.assertEqual(
+ _args_dict_from_uri('foo:key>=v1;key<v4;key!=v2;key!=v3', type_hints), {
+ 'key': [
+ ConstraintClass('v1', ConstraintClass.Op.GE),
+ ConstraintClass('v4', ConstraintClass.Op.LT),
+ ConstraintClass('v2', ConstraintClass.Op.NE),
+ ConstraintClass('v3', ConstraintClass.Op.NE),
+ ]
+ })
def _check_resolver_result(self,
foo_res,
diff --git a/src/protozero/protoc_plugin/protozero_plugin.cc b/src/protozero/protoc_plugin/protozero_plugin.cc
index 5b08292..7a29776 100644
--- a/src/protozero/protoc_plugin/protozero_plugin.cc
+++ b/src/protozero/protoc_plugin/protozero_plugin.cc
@@ -371,6 +371,12 @@
// name of this message is used to group them.
std::string extension_name = extension->extension_scope()->name();
extensions_[extension_name].push_back(extension);
+
+ if (extension->message_type()) {
+ // Emit a forward declaration of nested message types, as the outer
+ // class will refer to them when creating type aliases.
+ referenced_messages_.insert(extension->message_type());
+ }
}
} else {
messages_.push_back(message);
@@ -755,6 +761,14 @@
if (field->is_repeated() && !field->is_packed())
has_nonpacked_repeated_fields = true;
}
+ // Iterate over all fields in "extend" blocks.
+ for (int i = 0; i < message->extension_range_count(); ++i) {
+ const Descriptor::ExtensionRange* range = message->extension_range(i);
+ int candidate = range->end - 1;
+ if (candidate > kMaxDecoderFieldId)
+ continue;
+ max_field_id = std::max(max_field_id, candidate);
+ }
std::string class_name = GetCppClassName(message) + "_Decoder";
stub_h_->Print(
@@ -880,7 +894,8 @@
}
void GenerateConstantsForMessageFields(const Descriptor* message) {
- const bool has_fields = (message->field_count() > 0);
+ const bool has_fields =
+ message->field_count() > 0 || message->extension_count() > 0;
// Field number constants.
if (has_fields) {
@@ -893,6 +908,15 @@
GetFieldNumberConstant(field), "id",
std::to_string(field->number()));
}
+
+ for (int i = 0; i < message->extension_count(); ++i) {
+ const FieldDescriptor* field = message->extension(i);
+
+ stub_h_->Print("$name$ = $id$,\n", "name",
+ GetFieldNumberConstant(field), "id",
+ std::to_string(field->number()));
+ }
+
stub_h_->Outdent();
stub_h_->Print("};\n");
}
@@ -1049,6 +1073,20 @@
}
GenerateFieldDescriptor(extension_name, field);
}
+
+ if (!descriptors.empty()) {
+ stub_h_->Print("enum : int32_t {\n");
+ stub_h_->Indent();
+
+ for (const FieldDescriptor* field : descriptors) {
+ stub_h_->Print("$name$ = $id$,\n", "name",
+ GetFieldNumberConstant(field), "id",
+ std::to_string(field->number()));
+ }
+ stub_h_->Outdent();
+ stub_h_->Print("};\n");
+ }
+
stub_h_->Outdent();
stub_h_->Print("};\n");
}
diff --git a/src/trace_processor/importers/common/process_tracker.cc b/src/trace_processor/importers/common/process_tracker.cc
index e1d23a3..f034867 100644
--- a/src/trace_processor/importers/common/process_tracker.cc
+++ b/src/trace_processor/importers/common/process_tracker.cc
@@ -15,11 +15,11 @@
*/
#include "src/trace_processor/importers/common/process_tracker.h"
-#include "src/trace_processor/storage/stats.h"
-#include <cinttypes>
#include <utility>
+#include "src/trace_processor/storage/stats.h"
+
namespace perfetto {
namespace trace_processor {
@@ -102,7 +102,7 @@
// Remove the thread from the list of threads being tracked as any event after
// this one should be ignored.
auto& vector = tids_[tid];
- vector.erase(std::remove(vector.begin(), vector.end(), utid));
+ vector.erase(std::remove(vector.begin(), vector.end(), utid), vector.end());
auto opt_upid = thread_table->upid()[utid];
if (!opt_upid.has_value() || process_table->pid()[*opt_upid] != tid)
@@ -536,13 +536,11 @@
}
void ProcessTracker::SetPidZeroIsUpidZeroIdleProcess() {
- auto swapper_id = context_->storage->InternString("swapper");
-
// Create a mapping from (t|p)id 0 -> u(t|p)id for the idle process.
tids_.Insert(0, std::vector<UniqueTid>{swapper_utid_});
pids_.Insert(0, swapper_upid_);
- // Set the hardcoded, constant "swapper" thread name to the thread.
+ auto swapper_id = context_->storage->InternString("swapper");
UpdateThreadName(0, swapper_id, ThreadNamePriority::kTraceProcessorConstant);
}
diff --git a/src/trace_processor/importers/common/process_tracker.h b/src/trace_processor/importers/common/process_tracker.h
index 3808f99..e5ccd39 100644
--- a/src/trace_processor/importers/common/process_tracker.h
+++ b/src/trace_processor/importers/common/process_tracker.h
@@ -17,8 +17,11 @@
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_PROCESS_TRACKER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_PROCESS_TRACKER_H_
-#include <tuple>
+#include <stdint.h>
+
+#include <optional>
#include <unordered_set>
+#include <vector>
#include "perfetto/ext/base/flat_hash_map.h"
#include "perfetto/ext/base/string_view.h"
@@ -35,6 +38,7 @@
enum class ThreadNamePriority {
kOther = 0,
kFtrace = 1,
+ kEtwTrace = 1,
kProcessTree = 2,
kTrackDescriptorThreadType = 3,
kTrackDescriptor = 4,
diff --git a/src/trace_processor/importers/common/thread_state_tracker.cc b/src/trace_processor/importers/common/thread_state_tracker.cc
index 37d26d1..2d98ffb 100644
--- a/src/trace_processor/importers/common/thread_state_tracker.cc
+++ b/src/trace_processor/importers/common/thread_state_tracker.cc
@@ -15,8 +15,10 @@
*/
#include "src/trace_processor/importers/common/thread_state_tracker.h"
+
#include <cstdint>
#include <optional>
+
#include "src/trace_processor/importers/common/process_tracker.h"
namespace perfetto {
@@ -182,7 +184,10 @@
// If common_flags contains TRACE_FLAG_HARDIRQ | TRACE_FLAG_SOFTIRQ, wakeup
// was emitted in interrupt context.
// See:
- // https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/include/trace/trace_events.h
+ // https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/include/linux/trace_events.h
+ // TODO(rsavitski): we could also include TRACE_FLAG_NMI for a complete
+ // "interrupt context" meaning. But at the moment it's not necessary as this
+ // is used for sched_waking events, which are not emitted from NMI contexts.
return common_flags & (0x08 | 0x10) ? 1 : 0;
}
diff --git a/src/trace_processor/importers/common/trace_parser.cc b/src/trace_processor/importers/common/trace_parser.cc
index 6c586e0..608aca3 100644
--- a/src/trace_processor/importers/common/trace_parser.cc
+++ b/src/trace_processor/importers/common/trace_parser.cc
@@ -51,6 +51,9 @@
void TraceParser::ParseInlineSchedWaking(uint32_t, int64_t, InlineSchedWaking) {
PERFETTO_FATAL("Wrong parser type");
}
+void TraceParser::ParseEtwEvent(uint32_t, int64_t, TracePacketData) {
+ PERFETTO_FATAL("Wrong parser type");
+}
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/common/trace_parser.h b/src/trace_processor/importers/common/trace_parser.h
index d948d27..9c7098f 100644
--- a/src/trace_processor/importers/common/trace_parser.h
+++ b/src/trace_processor/importers/common/trace_parser.h
@@ -43,6 +43,7 @@
virtual void ParseTrackEvent(int64_t, TrackEventData);
virtual void ParseSystraceLine(int64_t, SystraceLine);
+ virtual void ParseEtwEvent(uint32_t, int64_t, TracePacketData);
virtual void ParseFtraceEvent(uint32_t, int64_t, TracePacketData);
virtual void ParseInlineSchedSwitch(uint32_t, int64_t, InlineSchedSwitch);
virtual void ParseInlineSchedWaking(uint32_t, int64_t, InlineSchedWaking);
diff --git a/src/trace_processor/importers/etw/BUILD.gn b/src/trace_processor/importers/etw/BUILD.gn
index d8985b1..23d8965 100644
--- a/src/trace_processor/importers/etw/BUILD.gn
+++ b/src/trace_processor/importers/etw/BUILD.gn
@@ -14,14 +14,30 @@
import("../../../../gn/test.gni")
-source_set("full") {
+source_set("minimal") {
sources = [
"etw_module.cc",
"etw_module.h",
+ ]
+ deps = [
+ "../../../../gn:default_deps",
+ "../common:parser_types",
+ "../common:trace_parser_hdr",
+ "../proto:proto_importer_module",
+ ]
+}
+
+source_set("full") {
+ sources = [
+ "etw_module_impl.cc",
+ "etw_module_impl.h",
+ "etw_parser.cc",
+ "etw_parser.h",
"etw_tokenizer.cc",
"etw_tokenizer.h",
]
deps = [
+ ":minimal",
"../../../../gn:default_deps",
"../../../../protos/perfetto/common:zero",
"../../../../protos/perfetto/trace:zero",
diff --git a/src/trace_processor/importers/etw/etw_module.cc b/src/trace_processor/importers/etw/etw_module.cc
index 508d2ca..a1a9d3f 100644
--- a/src/trace_processor/importers/etw/etw_module.cc
+++ b/src/trace_processor/importers/etw/etw_module.cc
@@ -15,37 +15,15 @@
*/
#include "src/trace_processor/importers/etw/etw_module.h"
-#include "perfetto/base/build_config.h"
-#include "perfetto/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/importers/etw/etw_tokenizer.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "src/trace_processor/importers/common/parser_types.h"
namespace perfetto {
namespace trace_processor {
-using perfetto::protos::pbzero::TracePacket;
-
-EtwModule::EtwModule(TraceProcessorContext* context) : tokenizer_(context) {
- RegisterForField(TracePacket::kEtwEventsFieldNumber, context);
-}
-
-ModuleResult EtwModule::TokenizePacket(
- const protos::pbzero::TracePacket::Decoder& decoder,
- TraceBlobView* packet,
- int64_t /*packet_timestamp*/,
- PacketSequenceState* seq_state,
- uint32_t field_id) {
- switch (field_id) {
- case TracePacket::kEtwEventsFieldNumber: {
- auto etw_field = decoder.etw_events();
- tokenizer_.TokenizeEtwBundle(
- packet->slice(etw_field.data, etw_field.size), seq_state);
- return ModuleResult::Handled();
- }
- }
- return ModuleResult::Ignored();
-}
+void EtwModule::ParseEtwEventData(uint32_t /*cpu*/,
+ int64_t /*ts*/,
+ const TracePacketData&) {}
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/etw/etw_module.h b/src/trace_processor/importers/etw/etw_module.h
index 1624af1..5f80271 100644
--- a/src/trace_processor/importers/etw/etw_module.h
+++ b/src/trace_processor/importers/etw/etw_module.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2024 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.
@@ -17,11 +17,7 @@
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_ETW_ETW_MODULE_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_ETW_ETW_MODULE_H_
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
#include "src/trace_processor/importers/common/parser_types.h"
-#include "src/trace_processor/importers/common/trace_parser.h"
-#include "src/trace_processor/importers/etw/etw_module.h"
-#include "src/trace_processor/importers/etw/etw_tokenizer.h"
#include "src/trace_processor/importers/proto/proto_importer_module.h"
namespace perfetto {
@@ -29,17 +25,9 @@
class EtwModule : public ProtoImporterModule {
public:
- explicit EtwModule(TraceProcessorContext* context);
-
- ModuleResult TokenizePacket(
- const protos::pbzero::TracePacket::Decoder& decoder,
- TraceBlobView* packet,
- int64_t packet_timestamp,
- PacketSequenceState* state,
- uint32_t field_id) override;
-
- private:
- EtwTokenizer tokenizer_;
+ virtual void ParseEtwEventData(uint32_t cpu,
+ int64_t ts,
+ const TracePacketData& data);
};
} // namespace trace_processor
diff --git a/src/trace_processor/importers/etw/etw_module_impl.cc b/src/trace_processor/importers/etw/etw_module_impl.cc
new file mode 100644
index 0000000..7c44d04
--- /dev/null
+++ b/src/trace_processor/importers/etw/etw_module_impl.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/importers/etw/etw_module_impl.h"
+
+#include "perfetto/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/importers/etw/etw_tokenizer.h"
+
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+using perfetto::protos::pbzero::TracePacket;
+
+EtwModuleImpl::EtwModuleImpl(TraceProcessorContext* context)
+ : tokenizer_(context), parser_(context) {
+ RegisterForField(TracePacket::kEtwEventsFieldNumber, context);
+}
+
+ModuleResult EtwModuleImpl::TokenizePacket(
+ const protos::pbzero::TracePacket::Decoder& decoder,
+ TraceBlobView* packet,
+ int64_t /*packet_timestamp*/,
+ PacketSequenceState* seq_state,
+ uint32_t field_id) {
+ switch (field_id) {
+ case TracePacket::kEtwEventsFieldNumber: {
+ auto etw_field = decoder.etw_events();
+ tokenizer_.TokenizeEtwBundle(
+ packet->slice(etw_field.data, etw_field.size), seq_state);
+ return ModuleResult::Handled();
+ }
+ }
+ return ModuleResult::Ignored();
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/etw/etw_module_impl.h b/src/trace_processor/importers/etw/etw_module_impl.h
new file mode 100644
index 0000000..af05fc8
--- /dev/null
+++ b/src/trace_processor/importers/etw/etw_module_impl.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_ETW_ETW_MODULE_IMPL_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_ETW_ETW_MODULE_IMPL_H_
+
+#include "src/trace_processor/importers/common/parser_types.h"
+#include "src/trace_processor/importers/etw/etw_module.h"
+#include "src/trace_processor/importers/etw/etw_parser.h"
+#include "src/trace_processor/importers/etw/etw_tokenizer.h"
+#include "src/trace_processor/importers/proto/proto_importer_module.h"
+
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceBlobView;
+
+class EtwModuleImpl : public EtwModule {
+ public:
+ explicit EtwModuleImpl(TraceProcessorContext* context);
+
+ ModuleResult TokenizePacket(
+ const protos::pbzero::TracePacket::Decoder& decoder,
+ TraceBlobView* packet,
+ int64_t packet_timestamp,
+ PacketSequenceState* state,
+ uint32_t field_id) override;
+
+ void ParseEtwEventData(uint32_t cpu,
+ int64_t ts,
+ const TracePacketData& data) override {
+ util::Status res = parser_.ParseEtwEvent(cpu, ts, data);
+ if (!res.ok()) {
+ PERFETTO_ELOG("%s", res.message().c_str());
+ }
+ }
+
+ private:
+ EtwTokenizer tokenizer_;
+ EtwParser parser_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_ETW_ETW_MODULE_IMPL_H_
diff --git a/src/trace_processor/importers/etw/etw_parser.cc b/src/trace_processor/importers/etw/etw_parser.cc
new file mode 100644
index 0000000..99f790d
--- /dev/null
+++ b/src/trace_processor/importers/etw/etw_parser.cc
@@ -0,0 +1,140 @@
+/*
+ etw* Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/importers/etw/etw_parser.h"
+
+#include "perfetto/ext/base/string_view.h"
+#include "src/trace_processor/importers/common/parser_types.h"
+#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/importers/common/sched_event_tracker.h"
+#include "src/trace_processor/importers/common/thread_state_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
+
+#include "protos/perfetto/trace/etw/etw.pbzero.h"
+#include "protos/perfetto/trace/etw/etw_event.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+
+using protozero::ConstBytes;
+
+} // namespace
+EtwParser::EtwParser(TraceProcessorContext* context) : context_(context) {}
+
+util::Status EtwParser::ParseEtwEvent(uint32_t cpu,
+ int64_t ts,
+ const TracePacketData& data) {
+ using protos::pbzero::EtwTraceEvent;
+ const TraceBlobView& event = data.packet;
+ protos::pbzero::EtwTraceEvent::Decoder decoder(event.data(), event.length());
+
+ if (decoder.has_c_switch()) {
+ ParseCswitch(ts, cpu, decoder.c_switch());
+ }
+
+ if (decoder.has_ready_thread()) {
+ ParseReadyThread(ts, decoder.ready_thread());
+ }
+
+ return util::OkStatus();
+}
+
+void EtwParser::ParseCswitch(int64_t timestamp, uint32_t cpu, ConstBytes blob) {
+ protos::pbzero::CSwitchEtwEvent::Decoder cs(blob.data, blob.size);
+ PushSchedSwitch(cpu, timestamp, cs.old_thread_id(), cs.old_thread_state(),
+ cs.new_thread_id(), cs.new_thread_priority());
+}
+
+void EtwParser::ParseReadyThread(int64_t timestamp, ConstBytes blob) {
+ protos::pbzero::ReadyThreadEtwEvent::Decoder rt(blob.data, blob.size);
+ UniqueTid utid =
+ context_->process_tracker->GetOrCreateThread(rt.t_thread_id());
+ ThreadStateTracker::GetOrCreate(context_)->PushWakingEvent(timestamp, utid,
+ utid);
+}
+
+void EtwParser::PushSchedSwitch(uint32_t cpu,
+ int64_t ts,
+ uint32_t prev_tid,
+ int64_t prev_state,
+ uint32_t next_tid,
+ int32_t next_prio) {
+ // At this stage all events should be globally timestamp ordered.
+ if (!context_->sched_event_tracker->UpdateEventTrackerTimestamp(
+ ts, "etw_cswitch", stats::sched_switch_out_of_order)) {
+ return;
+ }
+
+ UniqueTid next_utid = context_->process_tracker->GetOrCreateThread(next_tid);
+
+ // First use this data to close the previous slice.
+ bool prev_pid_match_prev_next_pid = false;
+ auto* pending_sched = sched_event_state_.GetPendingSchedInfoForCpu(cpu);
+ uint32_t pending_slice_idx = pending_sched->pending_slice_storage_idx;
+ StringId prev_state_string_id = TaskStateToStringId(prev_state);
+ if (prev_state_string_id == kNullStringId) {
+ context_->storage->IncrementStats(stats::task_state_invalid);
+ }
+ if (pending_slice_idx < std::numeric_limits<uint32_t>::max()) {
+ prev_pid_match_prev_next_pid = prev_tid == pending_sched->last_pid;
+ if (PERFETTO_LIKELY(prev_pid_match_prev_next_pid)) {
+ context_->sched_event_tracker->ClosePendingSlice(pending_slice_idx, ts,
+ prev_state_string_id);
+ } else {
+ // If the pids are not consistent, make a note of this.
+ context_->storage->IncrementStats(stats::mismatched_sched_switch_tids);
+ }
+ }
+
+ auto new_slice_idx = context_->sched_event_tracker->AddStartSlice(
+ cpu, ts, next_utid, next_prio);
+
+ // Finally, update the info for the next sched switch on this CPU.
+ pending_sched->pending_slice_storage_idx = new_slice_idx;
+ pending_sched->last_pid = next_tid;
+ pending_sched->last_utid = next_utid;
+ pending_sched->last_prio = next_prio;
+
+ UniqueTid prev_utid = context_->process_tracker->GetOrCreateThread(prev_tid);
+
+ // Update the ThreadState table.
+ ThreadStateTracker::GetOrCreate(context_)->PushSchedSwitchEvent(
+ ts, cpu, prev_utid, prev_state_string_id, next_utid);
+}
+
+StringId EtwParser::TaskStateToStringId(int64_t task_state_int) {
+ const auto state = static_cast<uint8_t>(task_state_int);
+ // Mapping for the different Etw states with their string description.
+ std::map<uint8_t, base::StringView> etw_states_map = {
+ {0x00, "Initialized"}, // INITIALIZED
+ {0x01, "R"}, // READY
+ {0x02, "Running"}, // RUNNING
+ {0x03, "Stand By"}, // STANDBY
+ {0x04, "T"}, // TERMINATED
+ {0x05, "Waiting"}, // WAITING
+ {0x06, "Transition"}, // TRANSITION
+ {0x07, "Deferred Ready"}, // DEFERRED_READY
+ };
+
+ return etw_states_map.find(state) != etw_states_map.end()
+ ? context_->storage->InternString(etw_states_map[state])
+ : kNullStringId;
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/etw/etw_parser.h b/src/trace_processor/importers/etw/etw_parser.h
new file mode 100644
index 0000000..380c6e8
--- /dev/null
+++ b/src/trace_processor/importers/etw/etw_parser.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_ETW_ETW_PARSER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_ETW_ETW_PARSER_H_
+
+#include "perfetto/protozero/field.h"
+#include "perfetto/trace_processor/status.h"
+#include "src/trace_processor/importers/common/parser_types.h"
+#include "src/trace_processor/importers/common/sched_event_state.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class EtwParser {
+ public:
+ explicit EtwParser(TraceProcessorContext* context);
+
+ util::Status ParseEtwEvent(uint32_t cpu,
+ int64_t ts,
+ const TracePacketData& data);
+
+ private:
+ void ParseCswitch(int64_t timestamp, uint32_t cpu, protozero::ConstBytes);
+ void ParseReadyThread(int64_t timestamp, protozero::ConstBytes);
+ void PushSchedSwitch(uint32_t cpu,
+ int64_t timestamp,
+ uint32_t prev_pid,
+ int64_t prev_state,
+ uint32_t next_pid,
+ int32_t next_prio);
+ StringId TaskStateToStringId(int64_t task_state_int);
+
+ TraceProcessorContext* context_;
+
+ SchedEventState sched_event_state_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_ETW_ETW_PARSER_H_
diff --git a/src/trace_processor/importers/etw/etw_tokenizer.cc b/src/trace_processor/importers/etw/etw_tokenizer.cc
index f07d74c..2474454 100644
--- a/src/trace_processor/importers/etw/etw_tokenizer.cc
+++ b/src/trace_processor/importers/etw/etw_tokenizer.cc
@@ -50,9 +50,11 @@
// in case the EtwTraceEvent does not contain the cpu.
std::optional<uint32_t> bundle_cpu =
decoder.has_cpu() ? std::make_optional(decoder.cpu()) : std::nullopt;
- auto it = decoder.event();
- return TokenizeEtwEvent(bundle_cpu, bundle.slice(it->data(), it->size()),
- state);
+
+ for (auto it = decoder.event(); it; ++it) {
+ TokenizeEtwEvent(bundle_cpu, bundle.slice(it->data(), it->size()), state);
+ }
+ return base::OkStatus();
}
PERFETTO_ALWAYS_INLINE
diff --git a/src/trace_processor/importers/etw/etw_tokenizer.h b/src/trace_processor/importers/etw/etw_tokenizer.h
index 1d93a14..6447ed2 100644
--- a/src/trace_processor/importers/etw/etw_tokenizer.h
+++ b/src/trace_processor/importers/etw/etw_tokenizer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.cc b/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.cc
index 2c0a962..a7b1ced 100644
--- a/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.cc
@@ -74,8 +74,8 @@
uint32_t next_pid,
base::StringView next_comm,
int32_t next_prio) {
- if (!context_->sched_event_tracker->UpdateEventTrackerTimestamp(ts,
- "sched_switch",stats::sched_switch_out_of_order)) {
+ if (!context_->sched_event_tracker->UpdateEventTrackerTimestamp(
+ ts, "sched_switch", stats::sched_switch_out_of_order)) {
return;
}
@@ -267,7 +267,6 @@
ts, wakee_utid, curr_utid, common_flags);
}
-PERFETTO_ALWAYS_INLINE
void FtraceSchedEventTracker::AddRawSchedSwitchEvent(uint32_t cpu,
int64_t ts,
UniqueTid prev_utid,
diff --git a/src/trace_processor/importers/proto/BUILD.gn b/src/trace_processor/importers/proto/BUILD.gn
index 0f2f53a..d40a84b 100644
--- a/src/trace_processor/importers/proto/BUILD.gn
+++ b/src/trace_processor/importers/proto/BUILD.gn
@@ -100,6 +100,7 @@
"../../util:profiler_util",
"../common",
"../common:parser_types",
+ "../etw:minimal",
"../ftrace:minimal",
"../json:minimal",
"../memory_tracker:graph_processor",
diff --git a/src/trace_processor/importers/proto/additional_modules.cc b/src/trace_processor/importers/proto/additional_modules.cc
index 83b13e5..91645c3 100644
--- a/src/trace_processor/importers/proto/additional_modules.cc
+++ b/src/trace_processor/importers/proto/additional_modules.cc
@@ -15,7 +15,7 @@
*/
#include "src/trace_processor/importers/proto/additional_modules.h"
-#include "src/trace_processor/importers/etw/etw_module.h"
+#include "src/trace_processor/importers/etw/etw_module_impl.h"
#include "src/trace_processor/importers/ftrace/ftrace_module_impl.h"
#include "src/trace_processor/importers/proto/android_camera_event_module.h"
#include "src/trace_processor/importers/proto/android_probes_module.h"
@@ -45,13 +45,14 @@
context->modules.emplace_back(new MetadataModule(context));
context->modules.emplace_back(new V8Module(context));
context->modules.emplace_back(new WinscopeModule(context));
- context->modules.emplace_back(new EtwModule(context));
- // Ftrace module is special, because it has one extra method for parsing
- // ftrace packets. So we need to store a pointer to it separately.
+ // Ftrace/Etw modules are special, because it has one extra method for parsing
+ // ftrace/etw packets. So we need to store a pointer to it separately.
context->modules.emplace_back(new FtraceModuleImpl(context));
context->ftrace_module =
static_cast<FtraceModule*>(context->modules.back().get());
+ context->modules.emplace_back(new EtwModuleImpl(context));
+ context->etw_module = static_cast<EtwModule*>(context->modules.back().get());
if (context->multi_machine_trace_manager) {
context->multi_machine_trace_manager->EnableAdditionalModules(
diff --git a/src/trace_processor/importers/proto/default_modules.cc b/src/trace_processor/importers/proto/default_modules.cc
index ca18beb..b1cfc93 100644
--- a/src/trace_processor/importers/proto/default_modules.cc
+++ b/src/trace_processor/importers/proto/default_modules.cc
@@ -15,6 +15,7 @@
*/
#include "src/trace_processor/importers/proto/default_modules.h"
+#include "src/trace_processor/importers/etw/etw_module.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
#include "src/trace_processor/importers/proto/chrome_system_probes_module.h"
#include "src/trace_processor/importers/proto/memory_tracker_snapshot_module.h"
@@ -28,10 +29,13 @@
void RegisterDefaultModules(TraceProcessorContext* context) {
context->modules.emplace_back(new FtraceModule());
- // Ftrace module is special, because it has one extra method for parsing
- // ftrace packets. So we need to store a pointer to it separately.
+ context->modules.emplace_back(new EtwModule());
+ // Ftrace and Etw modules are special, because they have an extra method for
+ // parsing the ftrace/etw packets. So we need to store a pointer to it
+ // separately.
context->ftrace_module =
static_cast<FtraceModule*>(context->modules.back().get());
+ context->etw_module = static_cast<EtwModule*>(context->modules.back().get());
context->modules.emplace_back(new TrackEventModule(context));
context->track_module =
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index 4043ec6..d81ef57 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -36,6 +36,7 @@
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/importers/etw/etw_module.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
#include "src/trace_processor/importers/proto/packet_sequence_state.h"
#include "src/trace_processor/importers/proto/track_event_module.h"
@@ -112,6 +113,18 @@
context_->args_tracker->Flush();
}
+void ProtoTraceParser::ParseEtwEvent(uint32_t cpu,
+ int64_t ts,
+ TracePacketData data) {
+ PERFETTO_DCHECK(context_->etw_module);
+ context_->etw_module->ParseEtwEventData(cpu, ts, data);
+
+ // TODO(lalitm): maybe move this to the flush method in the trace processor
+ // once we have it. This may reduce performance in the ArgsTracker though so
+ // needs to be handled carefully.
+ context_->args_tracker->Flush();
+}
+
void ProtoTraceParser::ParseFtraceEvent(uint32_t cpu,
int64_t ts,
TracePacketData data) {
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.h b/src/trace_processor/importers/proto/proto_trace_parser.h
index bfe5602..621bd02 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.h
+++ b/src/trace_processor/importers/proto/proto_trace_parser.h
@@ -49,6 +49,10 @@
void ParseTrackEvent(int64_t ts, TrackEventData data) override;
void ParseTracePacket(int64_t ts, TracePacketData data) override;
+ void ParseEtwEvent(uint32_t cpu,
+ int64_t /*ts*/,
+ TracePacketData data) override;
+
void ParseFtraceEvent(uint32_t cpu,
int64_t /*ts*/,
TracePacketData data) override;
diff --git a/src/trace_processor/perfetto_sql/stdlib/OWNERS b/src/trace_processor/perfetto_sql/stdlib/OWNERS
index 0479e4b..2d6db69 100644
--- a/src/trace_processor/perfetto_sql/stdlib/OWNERS
+++ b/src/trace_processor/perfetto_sql/stdlib/OWNERS
@@ -1,3 +1,5 @@
-# These can't be added inside chrome/ bacause the whole directory is
-# blown away on every import.
+# These can't be added inside chrome/ because the whole directory is
+# blown away on every import. Subdirectories of `chrome` will also
+# need CHROMIUM_OWNERS added here.
per-file chrome/* = file://protos/third_party/CHROMIUM_OWNERS
+per-file chrome/scroll_jank/* = file://protos/third_party/CHROMIUM_OWNERS
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/chrome_scrolls.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/chrome_scrolls.sql
index f6e29f9..fcc8933 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/chrome_scrolls.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/chrome_scrolls.sql
@@ -2,6 +2,8 @@
-- Use of this source code is governed by a BSD-style license that can be
-- found in the LICENSE file.
+INCLUDE PERFETTO MODULE chrome.scroll_jank.utils;
+
-- Defines slices for all of the individual scrolls in a trace based on the
-- LatencyInfo-based scroll definition.
--
@@ -19,36 +21,39 @@
ts INT,
-- The duration of the scroll.
dur INT,
- -- The earliest timestamp of the InputLatency::GestureScrollBegin for the
+ -- The earliest timestamp of the EventLatency slice of the GESTURE_SCROLL_BEGIN type for the
-- corresponding scroll id.
gesture_scroll_begin_ts INT,
- -- The earliest timestamp of the InputLatency::GestureScrollEnd for the
+ -- The earliest timestamp of the EventLatency slice of the GESTURE_SCROLL_END type /
+ -- the latest timestamp of the EventLatency slice of the GESTURE_SCROLL_UPDATE type for the
-- corresponding scroll id.
gesture_scroll_end_ts INT
) 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
+ args.string_value AS name,
+ S.ts AS ts,
+ S.dur AS dur,
+ chrome_get_most_recent_scroll_begin_id(S.ts) AS scroll_id
+ FROM slice AS S JOIN args USING(arg_set_id)
+ WHERE name="EventLatency"
+ AND args.string_value GLOB "*GESTURE_SCROLL*"
),
scroll_starts AS (
SELECT
scroll_id,
MIN(ts) AS gesture_scroll_begin_ts
FROM all_scrolls
- WHERE name = 'InputLatency::GestureScrollBegin'
+ WHERE name = "GESTURE_SCROLL_BEGIN"
GROUP BY scroll_id
-), scroll_ends AS (
+),
+scroll_ends AS (
SELECT
scroll_id,
- MIN(ts) AS gesture_scroll_end_ts
+ MAX(ts) AS gesture_scroll_end_ts
FROM all_scrolls
- WHERE name = 'InputLatency::GestureScrollEnd'
+ WHERE name GLOB "*GESTURE_SCROLL_UPDATE"
+ OR name = "GESTURE_SCROLL_END"
GROUP BY scroll_id
)
SELECT
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/utils.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/utils.sql
index 74141e6..b7b6bad 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/utils.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/utils.sql
@@ -103,3 +103,18 @@
WHERE
category GLOB "*scheduler.long_tasks*"
AND name = $name;
+
+-- Extracts scroll id for the EventLatency slice at `ts`.
+CREATE PERFETTO FUNCTION chrome_get_most_recent_scroll_begin_id(
+ -- Timestamp of the EventLatency slice to get the scroll id for.
+ ts INT)
+-- The event_latency_id of the EventLatency slice with the type
+-- GESTURE_SCROLL_BEGIN that is the closest to `ts`.
+RETURNS INT AS
+SELECT EXTRACT_ARG(arg_set_id, "event_latency.event_latency_id")
+FROM slice
+WHERE name="EventLatency"
+AND EXTRACT_ARG(arg_set_id, "event_latency.event_type") = "GESTURE_SCROLL_BEGIN"
+AND ts<=$ts
+ORDER BY ts DESC
+LIMIT 1;
diff --git a/src/trace_processor/perfetto_sql/stdlib/common/OWNERS b/src/trace_processor/perfetto_sql/stdlib/common/OWNERS
index a2788c4..0a16b3f 100644
--- a/src/trace_processor/perfetto_sql/stdlib/common/OWNERS
+++ b/src/trace_processor/perfetto_sql/stdlib/common/OWNERS
@@ -6,4 +6,3 @@
# For emergency reviews
primiano@google.com
-hjd@google.com
diff --git a/src/trace_processor/perfetto_sql/stdlib/sched/states.sql b/src/trace_processor/perfetto_sql/stdlib/sched/states.sql
index 37f759a..f6ce66a 100644
--- a/src/trace_processor/perfetto_sql/stdlib/sched/states.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/sched/states.sql
@@ -46,6 +46,12 @@
WHEN 'W' THEN 'Waking'
WHEN 'P' THEN 'Parked'
WHEN 'N' THEN 'No Load'
+-- ETW SPECIFIC STATES
+WHEN 'Stand By' THEN 'Stand By'
+WHEN 'Initialized' THEN 'Initialized'
+WHEN 'Waiting' THEN 'Waiting'
+WHEN 'Transition' THEN 'Transition'
+WHEN 'Deferred Ready' THEN 'Deferred Ready'
ELSE $short_name
END;
@@ -69,4 +75,4 @@
WHEN 0 THEN ' (non-IO)'
ELSE ''
END
-);
\ No newline at end of file
+);
diff --git a/src/trace_processor/sorter/trace_sorter.cc b/src/trace_processor/sorter/trace_sorter.cc
index b937e2e..e8159c3 100644
--- a/src/trace_processor/sorter/trace_sorter.cc
+++ b/src/trace_processor/sorter/trace_sorter.cc
@@ -211,18 +211,21 @@
return;
case TimestampedEvent::Type::kInlineSchedSwitch:
case TimestampedEvent::Type::kInlineSchedWaking:
- case TimestampedEvent::Type::kFtraceEvent:
case TimestampedEvent::Type::kEtwEvent:
+ case TimestampedEvent::Type::kFtraceEvent:
PERFETTO_FATAL("Invalid event type");
}
PERFETTO_FATAL("For GCC");
}
-void TraceSorter::ParseEtwPacket(TraceParser* /*parser*/,
- uint32_t /*cpu*/,
+void TraceSorter::ParseEtwPacket(TraceParser* parser,
+ uint32_t cpu,
const TimestampedEvent& event) {
+ TraceTokenBuffer::Id id = GetTokenBufferId(event);
switch (static_cast<TimestampedEvent::Type>(event.event_type)) {
case TimestampedEvent::Type::kEtwEvent:
+ parser->ParseEtwEvent(cpu, event.ts,
+ token_buffer_.Extract<TracePacketData>(id));
return;
case TimestampedEvent::Type::kInlineSchedSwitch:
case TimestampedEvent::Type::kInlineSchedWaking:
diff --git a/src/trace_redaction/BUILD.gn b/src/trace_redaction/BUILD.gn
index 3dc9cdf..be268d7 100644
--- a/src/trace_redaction/BUILD.gn
+++ b/src/trace_redaction/BUILD.gn
@@ -68,6 +68,8 @@
"scrub_process_trees.h",
"scrub_trace_packet.cc",
"scrub_trace_packet.h",
+ "suspend_resume.cc",
+ "suspend_resume.h",
"trace_redaction_framework.cc",
"trace_redaction_framework.h",
"trace_redactor.cc",
@@ -94,20 +96,22 @@
"filter_ftrace_using_allowlist_integrationtest.cc",
"filter_sched_waking_events_integrationtest.cc",
"filter_task_rename_integrationtest.cc",
+ "prune_package_list_integrationtest.cc",
"redact_sched_switch_integrationtest.cc",
"scrub_ftrace_events_integrationtest.cc",
"scrub_process_stats_integrationtest.cc",
"scrub_process_trees_integrationtest.cc",
"trace_redaction_integration_fixture.cc",
"trace_redaction_integration_fixture.h",
- "trace_redactor_integrationtest.cc",
]
deps = [
":trace_redaction",
"../../gn:default_deps",
"../../gn:gtest_and_gmock",
"../../include/perfetto/ext/base",
+ "../../protos/perfetto/trace:non_minimal_cpp",
"../../protos/perfetto/trace:non_minimal_zero",
+ "../../protos/perfetto/trace/android:cpp",
"../../protos/perfetto/trace/android:zero",
"../../protos/perfetto/trace/ftrace:zero",
"../../protos/perfetto/trace/ps:zero",
@@ -130,11 +134,13 @@
"redact_process_free_unittest.cc",
"redact_sched_switch_unittest.cc",
"redact_task_newtask_unittest.cc",
+ "suspend_resume_unittest.cc",
]
deps = [
":trace_redaction",
"../../gn:default_deps",
"../../gn:gtest_and_gmock",
+ "../../include/perfetto/ext/base:base",
"../../include/perfetto/protozero:protozero",
"../../protos/perfetto/config:cpp",
"../../protos/perfetto/config:zero",
diff --git a/src/trace_redaction/filter_ftrace_using_allowlist_integrationtest.cc b/src/trace_redaction/filter_ftrace_using_allowlist_integrationtest.cc
index 89946ae..e53770c 100644
--- a/src/trace_redaction/filter_ftrace_using_allowlist_integrationtest.cc
+++ b/src/trace_redaction/filter_ftrace_using_allowlist_integrationtest.cc
@@ -18,14 +18,11 @@
#include <string>
#include "perfetto/base/status.h"
-#include "perfetto/ext/base/file_utils.h"
#include "src/base/test/status_matchers.h"
-#include "src/base/test/tmp_dir_tree.h"
-#include "src/base/test/utils.h"
#include "src/trace_redaction/filter_ftrace_using_allowlist.h"
#include "src/trace_redaction/populate_allow_lists.h"
#include "src/trace_redaction/scrub_ftrace_events.h"
-#include "src/trace_redaction/trace_redaction_framework.h"
+#include "src/trace_redaction/trace_redaction_integration_fixture.h"
#include "src/trace_redaction/trace_redactor.h"
#include "test/gtest_and_gmock.h"
@@ -36,39 +33,15 @@
namespace perfetto::trace_redaction {
-class FilterFtraceUsingAllowlistTest : public testing::Test {
+class FilterFtraceUsingAllowlistTest
+ : public testing::Test,
+ protected TraceRedactionIntegrationFixure {
protected:
void SetUp() override {
- redactor_.emplace_build<PopulateAllowlists>();
-
- auto* scrub_ftrace_events =
- redactor_.emplace_transform<ScrubFtraceEvents>();
- scrub_ftrace_events->emplace_back<FilterFtraceUsingAllowlist>();
-
- src_trace_ =
- base::GetTestDataPath("test/data/trace-redaction-general.pftrace");
-
- dest_trace_ = tmp_dir_.AbsolutePath("dst.pftrace");
- }
-
- base::Status Redact() {
- auto status = redactor_.Redact(src_trace_, dest_trace_, &context_);
-
- // If redaction failed, the redactor should not have written the file to
- // disk.
- if (status.ok()) {
- tmp_dir_.TrackFile("dst.pftrace");
- }
-
- return status;
- }
-
- base::StatusOr<std::string> LoadOriginal() const {
- return ReadRawTrace(src_trace_);
- }
-
- base::StatusOr<std::string> LoadRedacted() const {
- return ReadRawTrace(dest_trace_);
+ trace_redactor()->emplace_build<PopulateAllowlists>();
+ trace_redactor()
+ ->emplace_transform<ScrubFtraceEvents>()
+ ->emplace_back<FilterFtraceUsingAllowlist>();
}
// Parse the given buffer and gather field ids from across all events. This
@@ -100,25 +73,6 @@
return event_ids;
}
-
- private:
- base::StatusOr<std::string> ReadRawTrace(const std::string& path) const {
- std::string redacted_buffer;
-
- if (base::ReadFile(path, &redacted_buffer)) {
- return redacted_buffer;
- }
-
- return base::ErrStatus("Failed to read %s", path.c_str());
- }
-
- Context context_;
- TraceRedactor redactor_;
-
- base::TmpDirTree tmp_dir_;
-
- std::string src_trace_;
- std::string dest_trace_;
};
// This is not a test of FilterFtraceUsingAllowlist, but instead verifies of the
diff --git a/src/trace_redaction/filter_packet_using_allowlist.cc b/src/trace_redaction/filter_packet_using_allowlist.cc
index 5b01c4d..b1a4dc4 100644
--- a/src/trace_redaction/filter_packet_using_allowlist.cc
+++ b/src/trace_redaction/filter_packet_using_allowlist.cc
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#include <string>
-
#include "perfetto/base/status.h"
#include "perfetto/protozero/field.h"
#include "src/trace_redaction/filter_packet_using_allowlist.h"
@@ -32,25 +30,11 @@
return base::OkStatus();
}
-bool FilterPacketUsingAllowlist::KeepPacket(const Context& context,
- const std::string& bytes) const {
+bool FilterPacketUsingAllowlist::KeepField(
+ const Context& context,
+ const protozero::Field& field) const {
PERFETTO_DCHECK(!context.trace_packet_allow_list.empty());
-
- const auto& allow_list = context.trace_packet_allow_list;
-
- protozero::ProtoDecoder decoder(bytes);
-
- // A packet should only have one data type (proto oneof), but there are other
- // values in the packet (e.g. timestamp). If one field is in the allowlist,
- // then allow the whole trace packet.
- for (auto field = decoder.ReadField(); field.valid();
- field = decoder.ReadField()) {
- if (allow_list.count(field.id()) != 0) {
- return true;
- }
- }
-
- return false;
+ return field.valid() && context.trace_packet_allow_list.count(field.id());
}
} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/filter_packet_using_allowlist.h b/src/trace_redaction/filter_packet_using_allowlist.h
index 7caa0ec..9205e94 100644
--- a/src/trace_redaction/filter_packet_using_allowlist.h
+++ b/src/trace_redaction/filter_packet_using_allowlist.h
@@ -31,8 +31,8 @@
public:
base::Status VerifyContext(const Context& context) const override;
- bool KeepPacket(const Context& context,
- const std::string& bytes) const override;
+ bool KeepField(const Context& context,
+ const protozero::Field& field) const override;
};
} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/filter_packet_using_allowlist_unittest.cc b/src/trace_redaction/filter_packet_using_allowlist_unittest.cc
index ffdb99f..fad6879 100644
--- a/src/trace_redaction/filter_packet_using_allowlist_unittest.cc
+++ b/src/trace_redaction/filter_packet_using_allowlist_unittest.cc
@@ -14,134 +14,59 @@
* limitations under the License.
*/
-#include <string>
-
-#include "src/base/test/status_matchers.h"
#include "src/trace_redaction/filter_packet_using_allowlist.h"
-#include "src/trace_redaction/scrub_trace_packet.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
#include "test/gtest_and_gmock.h"
-#include "protos/perfetto/trace/ps/process_tree.gen.h"
-#include "protos/perfetto/trace/trace_packet.gen.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
+// TODO(vaage): These tests were used to test the filter-driver, but these tests
+// no longer do that. A new test suite should be created to test the driver code
+// with the different filters.
namespace perfetto::trace_redaction {
-TEST(FilterPacketUsingAllowlistParamErrorTest, ReturnErrorForNullPacket) {
- ScrubTracePacket transform_;
- transform_.emplace_back<FilterPacketUsingAllowlist>();
+namespace {
- // Have something in the allow-list to avoid that error.
+constexpr auto kJustSomeFieldId =
+ protos::pbzero::TracePacket::kProcessTreeFieldNumber;
+
+} // namespace
+
+TEST(FilterPacketUsingAllowlistParamErrorTest, ReturnsErrorForEmptyAllowlist) {
Context context;
- context.trace_packet_allow_list.insert(
- protos::pbzero::TracePacket::kProcessTreeFieldNumber);
- ASSERT_FALSE(transform_.Transform(context, nullptr).ok());
+ FilterPacketUsingAllowlist filter;
+ auto status = filter.VerifyContext(context);
+
+ ASSERT_FALSE(status.ok()) << status.message();
}
-TEST(FilterPacketUsingAllowlistParamErrorTest, ReturnErrorForEmptyPacket) {
- ScrubTracePacket transform_;
- transform_.emplace_back<FilterPacketUsingAllowlist>();
-
- // Have something in the allow-list to avoid that error.
+TEST(FilterPacketUsingAllowlistParamErrorTest, ReturnsFalseForInvalidField) {
+ // Have something in the allow-list to avoid an error.
Context context;
- context.trace_packet_allow_list.insert(
- protos::pbzero::TracePacket::kProcessTreeFieldNumber);
+ context.trace_packet_allow_list.insert(kJustSomeFieldId);
- std::string packet_str = "";
+ protozero::Field invalid = {};
+ ASSERT_FALSE(invalid.valid());
- ASSERT_FALSE(transform_.Transform(context, &packet_str).ok());
+ FilterPacketUsingAllowlist filter;
+ ASSERT_FALSE(filter.KeepField(context, invalid));
}
-class FilterPacketUsingAllowlistTest : public testing::Test {
- protected:
- void SetUp() override {
- transform_.emplace_back<FilterPacketUsingAllowlist>();
- }
+TEST(FilterPacketUsingAllowlistParamErrorTest, ReturnsFalseForExcludedField) {
+ Context context;
+ context.trace_packet_allow_list.insert(kJustSomeFieldId);
- base::StatusOr<std::string> Redact(const protos::gen::TracePacket& packet) {
- auto str = packet.SerializeAsString();
- auto status = transform_.Transform(context_, &str);
+ protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+ packet->set_timestamp(123456789);
- if (status.ok()) {
- return str;
- }
+ auto buffer = packet.SerializeAsString();
- return status;
- }
+ protozero::ProtoDecoder decoder(buffer);
+ protozero::Field field = decoder.FindField(kJustSomeFieldId);
- Context context_;
-
- private:
- ScrubTracePacket transform_;
-};
-
-TEST_F(FilterPacketUsingAllowlistTest, ReturnErrorForEmptyAllowList) {
- // The context will have no allow-list entries. ScrubTracePacket should fail.
-
- protos::gen::TracePacket packet;
-
- auto status = Redact(packet);
- ASSERT_FALSE(status.ok()) << status.status().c_message();
-}
-
-// The whole packet should be dropped (cleared) when it has a data type not
-// included in the allow-list.
-TEST_F(FilterPacketUsingAllowlistTest, DropsOutsiderPacketType) {
- protos::gen::TracePacket packet;
- packet.set_timestamp(1234);
- packet.mutable_android_camera_frame_event(); // Creates and sets data.
-
- // Populate the allow-list with something that doesn't match the data in the
- // packet.
- context_.trace_packet_allow_list.insert(
- protos::pbzero::TracePacket::kProcessTreeFieldNumber);
-
- auto status = Redact(packet);
- ASSERT_OK(status) << status.status().c_message();
-
- ASSERT_TRUE(status->empty());
-}
-
-// Typically a trace packet should always have a data type (e.g. ProcessTree),
-// but it is possible that another transformation has cleared that data. If
-// that's the case, this primitive should treat it as an outsider.
-TEST_F(FilterPacketUsingAllowlistTest, DropsPacketsWithNoType) {
- protos::gen::TracePacket packet;
- packet.set_timestamp(1234);
-
- std::string packet_str = packet.SerializeAsString();
- ASSERT_GT(packet_str.size(), 0u);
-
- context_.trace_packet_allow_list.insert(
- protos::pbzero::TracePacket::kProcessTreeFieldNumber);
-
- auto status = Redact(packet);
- ASSERT_OK(status) << status.status().c_message();
-
- ASSERT_TRUE(status->empty());
-}
-
-// A packet should not change (at all) if it's in the allow-list.
-TEST_F(FilterPacketUsingAllowlistTest, SkipsAllowedPacket) {
- protos::gen::TracePacket packet;
- packet.set_timestamp(1234);
-
- // Add a process tree to the packet. Process trees are in the allow-list.
- auto* process = packet.mutable_process_tree()->add_processes();
- process->set_uid(0);
- process->set_ppid(3);
- process->set_pid(7);
-
- context_.trace_packet_allow_list.insert(
- protos::pbzero::TracePacket::kProcessTreeFieldNumber);
-
- auto status = Redact(packet);
- ASSERT_OK(status) << status.status().c_message();
-
- // The transform shouldn't have changed the string, so the string before and
- // after should match.
- ASSERT_EQ(*status, packet.SerializeAsString());
+ FilterPacketUsingAllowlist filter;
+ ASSERT_FALSE(filter.KeepField(context, field));
}
} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/main.cc b/src/trace_redaction/main.cc
index 3fa0080..656fdef 100644
--- a/src/trace_redaction/main.cc
+++ b/src/trace_redaction/main.cc
@@ -34,6 +34,7 @@
#include "src/trace_redaction/scrub_process_stats.h"
#include "src/trace_redaction/scrub_process_trees.h"
#include "src/trace_redaction/scrub_trace_packet.h"
+#include "src/trace_redaction/suspend_resume.h"
#include "src/trace_redaction/trace_redaction_framework.h"
#include "src/trace_redaction/trace_redactor.h"
@@ -51,6 +52,7 @@
// Add all builders.
redactor.emplace_build<PopulateAllowlists>();
+ redactor.emplace_build<AllowSuspendResume>();
redactor.emplace_build<OptimizeTimeline>();
// Add all transforms.
@@ -62,6 +64,7 @@
scrub_ftrace_events->emplace_back<FilterPrintEvents>();
scrub_ftrace_events->emplace_back<FilterSchedWakingEvents>();
scrub_ftrace_events->emplace_back<FilterTaskRename>();
+ scrub_ftrace_events->emplace_back<FilterSuspendResume>();
// Scrub packets and ftrace events first as they will remove the largest
// chucks of data from the trace. This will reduce the amount of data that the
diff --git a/src/trace_redaction/populate_allow_lists.cc b/src/trace_redaction/populate_allow_lists.cc
index 01da4a0..1c42bd1 100644
--- a/src/trace_redaction/populate_allow_lists.cc
+++ b/src/trace_redaction/populate_allow_lists.cc
@@ -25,8 +25,30 @@
namespace perfetto::trace_redaction {
base::Status PopulateAllowlists::Build(Context* context) const {
- if (!context->trace_packet_allow_list.empty()) {
- return base::ErrStatus("PopulateAllowlists: allow-list should be empty.");
+ // These fields are top-level fields that outside the "oneof data" field.
+ std::initializer_list<uint> required_trace_fields = {
+
+ protos::pbzero::TracePacket::kTimestampFieldNumber,
+ protos::pbzero::TracePacket::kTimestampClockIdFieldNumber,
+ protos::pbzero::TracePacket::kTrustedUidFieldNumber,
+ protos::pbzero::TracePacket::kTrustedPacketSequenceIdFieldNumber,
+ protos::pbzero::TracePacket::kTrustedPidFieldNumber,
+ protos::pbzero::TracePacket::kInternedDataFieldNumber,
+ protos::pbzero::TracePacket::kSequenceFlagsFieldNumber,
+
+ // DEPRECATED. Moved to SequenceFlags::SEQ_INCREMENTAL_STATE_CLEARED. So
+ // there is no reason to include it.
+ //
+ // protos::pbzero::TracePacket::incremental_state_cleared
+
+ protos::pbzero::TracePacket::kTracePacketDefaultsFieldNumber,
+ protos::pbzero::TracePacket::kPreviousPacketDroppedFieldNumber,
+ protos::pbzero::TracePacket::kFirstPacketOnSequenceFieldNumber,
+ protos::pbzero::TracePacket::kMachineIdFieldNumber,
+ };
+
+ for (auto item : required_trace_fields) {
+ context->trace_packet_allow_list.insert(item);
}
// TRACE PACKET NOTES
@@ -37,8 +59,7 @@
// constraints around keys or values, making fine-grain redaction
// difficult. Because this packet's value has no measurable, the safest
// option to drop the whole packet.
-
- context->trace_packet_allow_list = {
+ std::initializer_list<uint> trace_packets = {
protos::pbzero::TracePacket::kProcessTreeFieldNumber,
protos::pbzero::TracePacket::kProcessStatsFieldNumber,
protos::pbzero::TracePacket::kClockSnapshotFieldNumber,
@@ -59,13 +80,16 @@
protos::pbzero::TracePacket::kPackagesListFieldNumber,
};
- context->ftrace_packet_allow_list = {
+ for (auto item : trace_packets) {
+ context->trace_packet_allow_list.insert(item);
+ }
+
+ std::initializer_list<uint> ftrace_events = {
protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber,
protos::pbzero::FtraceEvent::kCpuFrequencyFieldNumber,
protos::pbzero::FtraceEvent::kCpuIdleFieldNumber,
protos::pbzero::FtraceEvent::kSchedBlockedReasonFieldNumber,
protos::pbzero::FtraceEvent::kSchedWakingFieldNumber,
- protos::pbzero::FtraceEvent::kSuspendResumeFieldNumber,
protos::pbzero::FtraceEvent::kTaskNewtaskFieldNumber,
protos::pbzero::FtraceEvent::kTaskRenameFieldNumber,
protos::pbzero::FtraceEvent::kSchedProcessFreeFieldNumber,
@@ -80,21 +104,9 @@
protos::pbzero::FtraceEvent::kPrintFieldNumber,
};
- // TODO: Some ftrace fields should be retained, but they carry too much risk
- // without additional redaction. This list should be configured in a build
- // primitive so that they can be optionally included.
- //
- // protos::pbzero::FtraceEvent::kPrintFieldNumber,
- //
- // TODO: Some fields will create new packets (e.g. binder calls may create
- // new spans. This is currently not supported (generated packets still
- // need to be redacted).
- //
- // protos::pbzero::FtraceEvent::kBinderTransactionFieldNumber,
- // protos::pbzero::FtraceEvent::kBinderTransactionReceivedFieldNumber,
- // protos::pbzero::FtraceEvent::kBinderSetPriorityFieldNumber,
- // protos::pbzero::FtraceEvent::kBinderLockedFieldNumber,
- // protos::pbzero::FtraceEvent::kBinderUnlockFieldNumber,
+ for (auto item : ftrace_events) {
+ context->ftrace_packet_allow_list.insert(item);
+ }
return base::OkStatus();
}
diff --git a/src/trace_redaction/prune_package_list_integrationtest.cc b/src/trace_redaction/prune_package_list_integrationtest.cc
new file mode 100644
index 0000000..8fd056a
--- /dev/null
+++ b/src/trace_redaction/prune_package_list_integrationtest.cc
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include "perfetto/base/status.h"
+#include "src/base/test/status_matchers.h"
+#include "src/trace_redaction/find_package_uid.h"
+#include "src/trace_redaction/prune_package_list.h"
+#include "src/trace_redaction/trace_redaction_framework.h"
+#include "src/trace_redaction/trace_redaction_integration_fixture.h"
+#include "src/trace_redaction/trace_redactor.h"
+#include "test/gtest_and_gmock.h"
+
+#include "protos/perfetto/trace/android/packages_list.gen.h"
+#include "protos/perfetto/trace/android/packages_list.pbzero.h"
+#include "protos/perfetto/trace/trace.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto::trace_redaction {
+
+namespace {
+
+// Set the package name to "just some package name". If a specific package name
+// is needed, the test it should overwrite this value.
+constexpr std::string_view kPackageName =
+ "com.Unity.com.unity.multiplayer.samples.coop";
+constexpr uint64_t kPackageUid = 10252;
+
+} // namespace
+
+class PrunePackageListIntegrationTest
+ : public testing::Test,
+ protected TraceRedactionIntegrationFixure {
+ protected:
+ void SetUp() override {
+ context()->package_name = kPackageName;
+
+ trace_redactor()->emplace_collect<FindPackageUid>();
+ trace_redactor()->emplace_transform<PrunePackageList>();
+ }
+
+ std::vector<protos::gen::PackagesList::PackageInfo> GetPackageInfo(
+ const protos::pbzero::Trace::Decoder& trace) const {
+ std::vector<protos::gen::PackagesList::PackageInfo> packages;
+
+ for (auto packet_it = trace.packet(); packet_it; ++packet_it) {
+ protos::pbzero::TracePacket::Decoder packet(*packet_it);
+
+ if (!packet.has_packages_list()) {
+ continue;
+ }
+
+ protos::pbzero::PackagesList::Decoder list(packet.packages_list());
+
+ for (auto info = list.packages(); info; ++info) {
+ auto& item = packages.emplace_back();
+ item.ParseFromArray(info->data(), info->size());
+ }
+ }
+
+ return packages;
+ }
+
+ std::vector<std::string> GetPackageNames(
+ const protos::pbzero::Trace::Decoder& trace) const {
+ std::vector<std::string> names;
+
+ for (const auto& package : GetPackageInfo(trace)) {
+ if (package.has_name()) {
+ names.push_back(package.name());
+ }
+ }
+
+ return names;
+ }
+};
+
+// It is possible for two packages_list to appear in the trace. The
+// find_package_uid will stop after the first one is found. Package uids are
+// appear as n * 1,000,000 where n is some integer. It is also possible for two
+// packages_list to contain copies of each other - for example
+// "com.Unity.com.unity.multiplayer.samples.coop" appears in both packages_list.
+TEST_F(PrunePackageListIntegrationTest, FindsPackageAndFiltersPackageList) {
+ auto result = Redact();
+ ASSERT_OK(result) << result.message();
+
+ auto after_raw_trace = LoadRedacted();
+ ASSERT_OK(after_raw_trace) << after_raw_trace.status().message();
+
+ ASSERT_TRUE(context()->package_uid.has_value());
+ ASSERT_EQ(NormalizeUid(context()->package_uid.value()),
+ NormalizeUid(kPackageUid));
+
+ protos::pbzero::Trace::Decoder redacted_trace(after_raw_trace.value());
+ auto packages = GetPackageInfo(redacted_trace);
+
+ ASSERT_EQ(packages.size(), 2u);
+
+ for (const auto& package : packages) {
+ ASSERT_TRUE(package.has_name());
+ ASSERT_EQ(package.name(), kPackageName);
+
+ ASSERT_TRUE(package.has_uid());
+ ASSERT_EQ(NormalizeUid(package.uid()), NormalizeUid(kPackageUid));
+ }
+}
+
+// It is possible for multiple packages to share a uid. The names will appears
+// across multiple package lists. The only time the package name appears is in
+// the package list, so there is no way to differentiate these packages (only
+// the uid is used later), so each entry should remain.
+TEST_F(PrunePackageListIntegrationTest, RetainsAllInstancesOfUid) {
+ context()->package_name = "com.google.android.networkstack.tethering";
+
+ auto result = Redact();
+ ASSERT_OK(result) << result.message();
+
+ auto after_raw_trace = LoadRedacted();
+ ASSERT_OK(after_raw_trace) << after_raw_trace.status().message();
+
+ protos::pbzero::Trace::Decoder redacted_trace(after_raw_trace.value());
+ auto package_names = GetPackageNames(redacted_trace);
+
+ std::vector<std::string> expected_package_names = {
+ "com.google.android.cellbroadcastservice",
+ "com.google.android.cellbroadcastservice",
+ "com.google.android.networkstack",
+ "com.google.android.networkstack",
+ "com.google.android.networkstack.permissionconfig",
+ "com.google.android.networkstack.permissionconfig",
+ "com.google.android.networkstack.tethering",
+ "com.google.android.networkstack.tethering",
+ };
+
+ // Sort to make compare possible.
+ std::sort(expected_package_names.begin(), expected_package_names.end());
+ std::sort(package_names.begin(), package_names.end());
+
+ ASSERT_TRUE(std::equal(package_names.begin(), package_names.end(),
+ expected_package_names.begin(),
+ expected_package_names.end()));
+}
+
+} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/scrub_ftrace_events_integrationtest.cc b/src/trace_redaction/scrub_ftrace_events_integrationtest.cc
index 7584b0f..50853c6 100644
--- a/src/trace_redaction/scrub_ftrace_events_integrationtest.cc
+++ b/src/trace_redaction/scrub_ftrace_events_integrationtest.cc
@@ -14,63 +14,37 @@
* limitations under the License.
*/
-#include <string>
-#include <string_view>
#include <vector>
#include "perfetto/base/status.h"
-#include "perfetto/ext/base/file_utils.h"
#include "src/base/test/status_matchers.h"
-#include "src/base/test/utils.h"
#include "src/trace_redaction/scrub_ftrace_events.h"
#include "src/trace_redaction/trace_redaction_framework.h"
+#include "src/trace_redaction/trace_redaction_integration_fixture.h"
#include "test/gtest_and_gmock.h"
#include "protos/perfetto/trace//ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/android/packages_list.pbzero.h"
#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
namespace perfetto::trace_redaction {
-namespace {
-using FtraceEvent = protos::pbzero::FtraceEvent;
-using PackagesList = protos::pbzero::PackagesList;
-using PackageInfo = protos::pbzero::PackagesList::PackageInfo;
-using Trace = protos::pbzero::Trace;
-using TracePacket = protos::pbzero::TracePacket;
-
-constexpr std::string_view kTracePath =
- "test/data/trace-redaction-general.pftrace";
-
// Runs ScrubFtraceEvents over an actual trace, verifying packet integrity when
// fields are removed.
-class ScrubFtraceEventsIntegrationTest : public testing::Test {
+class ScrubFtraceEventsIntegrationTest
+ : public testing::Test,
+ protected TraceRedactionIntegrationFixure {
public:
ScrubFtraceEventsIntegrationTest() = default;
~ScrubFtraceEventsIntegrationTest() override = default;
protected:
void SetUp() override {
- src_trace_ = base::GetTestDataPath(std::string(kTracePath));
- context_.ftrace_packet_allow_list.insert(
+ context()->ftrace_packet_allow_list.insert(
protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber);
- }
- std::string src_trace_;
-
- Context context_; // Used for allowlist.
- ScrubFtraceEvents transform_;
-
- static base::StatusOr<std::string> ReadRawTrace(const std::string& path) {
- std::string redacted_buffer;
-
- if (base::ReadFile(path, &redacted_buffer)) {
- return redacted_buffer;
- }
-
- return base::ErrStatus("Failed to read %s", path.c_str());
+ trace_redactor()->emplace_transform<ScrubFtraceEvents>();
}
// Gets spans for `event` messages that contain `sched_switch` messages.
@@ -137,23 +111,34 @@
};
TEST_F(ScrubFtraceEventsIntegrationTest, FindsPackageAndFiltersPackageList) {
- const auto& src_file = src_trace_;
+ auto redacted = Redact();
+ ASSERT_OK(redacted) << redacted.message();
- auto raw_src_trace = ReadRawTrace(src_file);
- ASSERT_OK(raw_src_trace);
+ // Load source.
+ auto before_raw_trace = LoadOriginal();
+ ASSERT_OK(before_raw_trace) << before_raw_trace.status().message();
+ protos::pbzero::Trace::Decoder before_trace(before_raw_trace.value());
+ auto before_it = before_trace.packet();
- protos::pbzero::Trace::Decoder source_trace(raw_src_trace.value());
+ // Load redacted.
+ auto after_raw_trace = LoadRedacted();
+ ASSERT_OK(after_raw_trace) << after_raw_trace.status().message();
+ protos::pbzero::Trace::Decoder after_trace(after_raw_trace.value());
+ auto after_it = after_trace.packet();
- for (auto packet_it = source_trace.packet(); packet_it; ++packet_it) {
- auto packet = packet_it->as_std_string();
- ASSERT_OK(transform_.Transform(context_, &packet));
+ while (before_it && after_it) {
+ protos::pbzero::TracePacket::Decoder before_packet(*before_it);
+ protos::pbzero::TracePacket::Decoder after_packet(*after_it);
- protos::pbzero::TracePacket::Decoder left_packet(*packet_it);
- protos::pbzero::TracePacket::Decoder right_packet(packet);
+ ComparePackets(std::move(before_packet), std::move(after_packet));
- ComparePackets(std::move(left_packet), std::move(right_packet));
+ ++before_it;
+ ++after_it;
}
+
+ // Both should be at the end.
+ ASSERT_FALSE(before_it);
+ ASSERT_FALSE(after_it);
}
-} // namespace
} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/scrub_trace_packet.cc b/src/trace_redaction/scrub_trace_packet.cc
index b8275e5..77ff55c 100644
--- a/src/trace_redaction/scrub_trace_packet.cc
+++ b/src/trace_redaction/scrub_trace_packet.cc
@@ -19,6 +19,9 @@
#include "src/trace_redaction/scrub_trace_packet.h"
#include "perfetto/base/status.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "src/trace_processor/util/status_macros.h"
+#include "src/trace_redaction/proto_util.h"
namespace perfetto::trace_redaction {
@@ -31,26 +34,29 @@
}
for (const auto& filter : filters_) {
- auto status = filter->VerifyContext(context);
+ RETURN_IF_ERROR(filter->VerifyContext(context));
+ }
- if (!status.ok()) {
- return status;
+ protozero::HeapBuffered<protos::pbzero::TracePacket> new_packet;
+
+ protozero::ProtoDecoder decoder(*packet);
+
+ for (auto field = decoder.ReadField(); field.valid();
+ field = decoder.ReadField()) {
+ if (KeepEvent(context, field)) {
+ proto_util::AppendField(field, new_packet.get());
}
}
- if (KeepEvent(context, *packet)) {
- return base::OkStatus();
- }
-
- packet->clear();
+ packet->assign(new_packet.SerializeAsString());
return base::OkStatus();
}
-// Logical AND of all filters.
+// Logical AND all filters.
bool ScrubTracePacket::KeepEvent(const Context& context,
- const std::string& bytes) const {
+ const protozero::Field& field) const {
for (const auto& filter : filters_) {
- if (!filter->KeepPacket(context, bytes)) {
+ if (!filter->KeepField(context, field)) {
return false;
}
}
diff --git a/src/trace_redaction/scrub_trace_packet.h b/src/trace_redaction/scrub_trace_packet.h
index 38dd2f1..331cccf 100644
--- a/src/trace_redaction/scrub_trace_packet.h
+++ b/src/trace_redaction/scrub_trace_packet.h
@@ -28,8 +28,10 @@
// Checks if the context contains all neccessary parameters.
virtual base::Status VerifyContext(const Context& context) const = 0;
- virtual bool KeepPacket(const Context& context,
- const std::string& bytes) const = 0;
+ // Checks if the field should be pass onto the new packet. Checks are a
+ // logical AND, so all filters must return true.
+ virtual bool KeepField(const Context& context,
+ const protozero::Field& field) const = 0;
};
class ScrubTracePacket : public TransformPrimitive {
@@ -43,7 +45,7 @@
}
private:
- bool KeepEvent(const Context& context, const std::string& bytes) const;
+ bool KeepEvent(const Context& context, const protozero::Field& field) const;
std::vector<std::unique_ptr<TracePacketFilter>> filters_;
};
diff --git a/src/trace_redaction/suspend_resume.cc b/src/trace_redaction/suspend_resume.cc
new file mode 100644
index 0000000..243446f
--- /dev/null
+++ b/src/trace_redaction/suspend_resume.cc
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_redaction/suspend_resume.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "protos/perfetto/trace/ftrace/power.pbzero.h"
+
+namespace perfetto::trace_redaction {
+
+base::Status AllowSuspendResume::Build(Context* context) const {
+ context->ftrace_packet_allow_list.insert(
+ protos::pbzero::FtraceEvent::kSuspendResumeFieldNumber);
+
+ // Values are taken from "suspend_period.textproto".
+ context->suspend_result_allow_list.insert("syscore_suspend");
+ context->suspend_result_allow_list.insert("syscore_resume");
+ context->suspend_result_allow_list.insert("timekeeping_freeze");
+
+ return base::OkStatus();
+}
+
+base::Status FilterSuspendResume::VerifyContext(const Context&) const {
+ // FilterSuspendResume could check if kSuspendResumeFieldNumber is present in
+ // ftrace_packet_allow_list and there are values in the
+ // suspend_result_allow_list, but would make it hard to enable/disable
+ // suspend-resume redaction.
+ return base::OkStatus();
+}
+
+// The ftrace event is passed in.
+bool FilterSuspendResume::KeepEvent(const Context& context,
+ protozero::ConstBytes bytes) const {
+ protozero::ProtoDecoder event_decoder(bytes);
+
+ auto suspend_resume = event_decoder.FindField(
+ protos::pbzero::FtraceEvent::kSuspendResumeFieldNumber);
+
+ // It's not a suspend-resume event, defer the decision to another filter.
+ if (!suspend_resume.valid()) {
+ return true;
+ }
+
+ protozero::ProtoDecoder suspend_resume_decoder(suspend_resume.as_bytes());
+
+ auto action = suspend_resume_decoder.FindField(
+ protos::pbzero::SuspendResumeFtraceEvent::kActionFieldNumber);
+
+ return !action.valid() ||
+ context.suspend_result_allow_list.count(action.as_std_string());
+}
+
+} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/suspend_resume.h b/src/trace_redaction/suspend_resume.h
new file mode 100644
index 0000000..09f7bd8
--- /dev/null
+++ b/src/trace_redaction/suspend_resume.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_REDACTION_SUSPEND_RESUME_H_
+#define SRC_TRACE_REDACTION_SUSPEND_RESUME_H_
+
+#include "src/trace_redaction/scrub_ftrace_events.h"
+#include "src/trace_redaction/trace_redaction_framework.h"
+
+namespace perfetto::trace_redaction {
+
+// Updates allowlists to include suspend-resume events and which events to allow
+// through.
+class AllowSuspendResume : public BuildPrimitive {
+ public:
+ base::Status Build(Context* context) const override;
+};
+
+// Filters ftrace events based on the suspend-resume event.
+class FilterSuspendResume : public FtraceEventFilter {
+ public:
+ base::Status VerifyContext(const Context& context) const override;
+
+ bool KeepEvent(const Context& context,
+ protozero::ConstBytes bytes) const override;
+};
+
+} // namespace perfetto::trace_redaction
+
+#endif // SRC_TRACE_REDACTION_SUSPEND_RESUME_H_
diff --git a/src/trace_redaction/suspend_resume_unittest.cc b/src/trace_redaction/suspend_resume_unittest.cc
new file mode 100644
index 0000000..7cf498a
--- /dev/null
+++ b/src/trace_redaction/suspend_resume_unittest.cc
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_redaction/suspend_resume.h"
+#include "src/base/test/status_matchers.h"
+#include "test/gtest_and_gmock.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"
+#include "protos/perfetto/trace/ftrace/power.gen.h"
+
+namespace perfetto::trace_redaction {
+
+TEST(AllowSuspendResumeTest, UpdatesTracePacketAllowlist) {
+ Context context;
+
+ // Start with a non-empty allow-list item.
+ context.ftrace_packet_allow_list.insert(
+ protos::pbzero::FtraceEvent::kPrintFieldNumber);
+
+ ASSERT_EQ(context.ftrace_packet_allow_list.size(), 1u);
+
+ AllowSuspendResume allow;
+ auto status = allow.Build(&context);
+ ASSERT_OK(status) << status.message();
+
+ // Print should still be present. The allowlist should have been updated, not
+ // replaced.
+ ASSERT_EQ(context.ftrace_packet_allow_list.count(
+ protos::pbzero::FtraceEvent::kPrintFieldNumber),
+ 1u);
+
+ ASSERT_EQ(context.ftrace_packet_allow_list.count(
+ protos::pbzero::FtraceEvent::kSuspendResumeFieldNumber),
+ 1u);
+}
+
+TEST(AllowSuspendResumeTest, UpdatesSuspendResumeAllowlist) {
+ Context context;
+
+ ASSERT_TRUE(context.suspend_result_allow_list.empty());
+
+ AllowSuspendResume allow;
+ auto status = allow.Build(&context);
+ ASSERT_OK(status) << status.message();
+
+ ASSERT_FALSE(context.suspend_result_allow_list.empty());
+}
+
+class SuspendResumeTest : public testing::Test {
+ protected:
+ void SetUp() {
+ AllowSuspendResume allow;
+ ASSERT_OK(allow.Build(&context_));
+ }
+
+ protos::gen::FtraceEvent CreateSuspendResumeEvent(
+ const std::string* action) const {
+ protos::gen::FtraceEvent event;
+ event.set_timestamp(1234);
+ event.set_pid(0);
+
+ auto* suspend_resume = event.mutable_suspend_resume();
+
+ if (action) {
+ suspend_resume->set_action(*action);
+ }
+
+ return event;
+ }
+
+ protos::gen::FtraceEvent CreateOtherEvent() const {
+ protos::gen::FtraceEvent event;
+ event.set_timestamp(1234);
+ event.set_pid(0);
+
+ auto* print = event.mutable_print();
+ print->set_buf("This is a message");
+
+ return event;
+ }
+
+ const Context& context() const { return context_; }
+
+ private:
+ Context context_;
+};
+
+// The suspend-resume filter is not responsible for non-suspend-resume events.
+// It should assume that another filter will handle it and it should just allow
+// those events through
+TEST_F(SuspendResumeTest, AcceptsOtherEvents) {
+ auto event = CreateOtherEvent();
+ auto event_array = event.SerializeAsArray();
+ protozero::ConstBytes event_bytes{event_array.data(), event_array.size()};
+
+ FilterSuspendResume filter;
+ ASSERT_TRUE(filter.KeepEvent(context(), event_bytes));
+}
+
+TEST_F(SuspendResumeTest, AcceptsEventsWithNoName) {
+ auto event = CreateSuspendResumeEvent(nullptr);
+ auto event_array = event.SerializeAsArray();
+ protozero::ConstBytes event_bytes{event_array.data(), event_array.size()};
+
+ Context context;
+
+ FilterSuspendResume filter;
+ ASSERT_TRUE(filter.KeepEvent(context, event_bytes));
+}
+
+TEST_F(SuspendResumeTest, AcceptsEventsWithValidName) {
+ // This value is from "src/trace_redaction/suspend_resume.cc".
+ std::string name = "syscore_suspend";
+
+ auto event = CreateSuspendResumeEvent(&name);
+ auto event_array = event.SerializeAsArray();
+ protozero::ConstBytes event_bytes{event_array.data(), event_array.size()};
+
+ FilterSuspendResume filter;
+ ASSERT_TRUE(filter.KeepEvent(context(), event_bytes));
+}
+
+TEST_F(SuspendResumeTest, RejectsEventsWithInvalidName) {
+ std::string name = "hello world";
+
+ auto event = CreateSuspendResumeEvent(&name);
+ auto event_array = event.SerializeAsArray();
+ protozero::ConstBytes event_bytes{event_array.data(), event_array.size()};
+
+ FilterSuspendResume filter;
+ ASSERT_FALSE(filter.KeepEvent(context(), event_bytes));
+}
+
+} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/trace_redaction_framework.h b/src/trace_redaction/trace_redaction_framework.h
index c1c7e45..f741f9b 100644
--- a/src/trace_redaction/trace_redaction_framework.h
+++ b/src/trace_redaction/trace_redaction_framework.h
@@ -24,7 +24,6 @@
#include "perfetto/base/flat_set.h"
#include "perfetto/base/status.h"
-#include "perfetto/ext/base/status_or.h"
#include "src/trace_redaction/process_thread_timeline.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
@@ -159,6 +158,17 @@
// ftrace event
base::FlatSet<uint32_t> ftrace_packet_allow_list;
+ // message SuspendResumeFtraceEvent {
+ // optional string action = 1 [(datapol.semantic_type) = ST_NOT_REQUIRED];
+ // optional int32 val = 2;
+ // optional uint32 start = 3 [(datapol.semantic_type) = ST_NOT_REQUIRED];
+ // }
+ //
+ // The "action" in SuspendResumeFtraceEvent is a free-form string. There are
+ // some know and expected values. Those values are stored here and all events
+ // who's action value is not found here, the ftrace event will be dropped.
+ base::FlatSet<std::string> suspend_result_allow_list;
+
// The timeline is a query-focused data structure that connects a pid to a
// uid at specific point in time.
//
diff --git a/src/trace_redaction/trace_redactor.cc b/src/trace_redaction/trace_redactor.cc
index fa56af4..60e8188 100644
--- a/src/trace_redaction/trace_redactor.cc
+++ b/src/trace_redaction/trace_redactor.cc
@@ -55,19 +55,13 @@
trace_processor::TraceBlobView whole_view(
trace_processor::TraceBlob::FromMmap(std::move(mapped)));
- // TODO(vaage): Update other status code to use RETURN_IF_ERROR.
RETURN_IF_ERROR(Collect(context, whole_view));
- if (auto status = Build(context); !status.ok()) {
- return status;
+ for (const auto& builder : builders_) {
+ RETURN_IF_ERROR(builder->Build(context));
}
- if (auto status = Transform(*context, whole_view, std::string(dest_filename));
- !status.ok()) {
- return status;
- }
-
- return base::OkStatus();
+ return Transform(*context, whole_view, std::string(dest_filename));
}
base::Status TraceRedactor::Collect(
@@ -94,16 +88,6 @@
return base::OkStatus();
}
-base::Status TraceRedactor::Build(Context* context) const {
- for (const auto& builder : builders_) {
- if (auto status = builder->Build(context); !status.ok()) {
- return status;
- }
- }
-
- return base::OkStatus();
-}
-
base::Status TraceRedactor::Transform(
const Context& context,
const trace_processor::TraceBlobView& view,
@@ -128,10 +112,7 @@
break;
}
- if (auto status = transformer->Transform(context, &packet);
- !status.ok()) {
- return status;
- }
+ RETURN_IF_ERROR(transformer->Transform(context, &packet));
}
// The packet has been removed from the trace. Don't write an empty packet
diff --git a/src/trace_redaction/trace_redactor_integrationtest.cc b/src/trace_redaction/trace_redactor_integrationtest.cc
deleted file mode 100644
index a62359f..0000000
--- a/src/trace_redaction/trace_redactor_integrationtest.cc
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <cstdint>
-#include <string>
-#include <string_view>
-#include <vector>
-
-#include "perfetto/base/status.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "src/base/test/status_matchers.h"
-#include "src/base/test/tmp_dir_tree.h"
-#include "src/base/test/utils.h"
-#include "src/trace_redaction/find_package_uid.h"
-#include "src/trace_redaction/prune_package_list.h"
-#include "src/trace_redaction/trace_redaction_framework.h"
-#include "src/trace_redaction/trace_redactor.h"
-#include "test/gtest_and_gmock.h"
-
-#include "protos/perfetto/trace/android/packages_list.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto::trace_redaction {
-
-// TODO(vaage): Add tests for the untested and/or included primitives:
-//
-// 1. Scrub process tree
-
-namespace {
-using FtraceEvent = protos::pbzero::FtraceEvent;
-
-constexpr std::string_view kTracePath =
- "test/data/trace-redaction-general.pftrace";
-
-// Set the package name to "just some package name". If a specific package name
-// is needed, the test it should overwrite this value.
-constexpr std::string_view kPackageName =
- "com.Unity.com.unity.multiplayer.samples.coop";
-constexpr uint64_t kPackageUid = 10252;
-
-class TraceRedactorIntegrationTest : public testing::Test {
- protected:
- void SetUp() override {
- src_trace_ = base::GetTestDataPath(std::string(kTracePath));
- context_.package_name = kPackageName;
- }
-
- const std::string& src_trace() const { return src_trace_; }
-
- static base::StatusOr<std::string> ReadRawTrace(const std::string& path) {
- std::string redacted_buffer;
-
- if (base::ReadFile(path, &redacted_buffer)) {
- return redacted_buffer;
- }
-
- return base::ErrStatus("Failed to read %s", path.c_str());
- }
-
- std::string src_trace_;
- base::TmpDirTree tmp_dir_;
-
- Context context_;
- TraceRedactor redactor_;
-};
-
-class PackageListTraceRedactorIntegrationTest
- : public TraceRedactorIntegrationTest {
- protected:
- void SetUp() override {
- TraceRedactorIntegrationTest::SetUp();
-
- redactor_.emplace_collect<FindPackageUid>();
- redactor_.emplace_transform<PrunePackageList>();
- }
-
- std::vector<protozero::ConstBytes> GetPackageInfos(
- const protos::pbzero::Trace::Decoder& trace) const {
- std::vector<protozero::ConstBytes> infos;
-
- for (auto packet_it = trace.packet(); packet_it; ++packet_it) {
- protos::pbzero::TracePacket::Decoder packet_decoder(*packet_it);
- if (packet_decoder.has_packages_list()) {
- protos::pbzero::PackagesList::Decoder list_it(
- packet_decoder.packages_list());
- for (auto info_it = list_it.packages(); info_it; ++info_it) {
- protos::pbzero::PackagesList::PackageInfo::Decoder info(*info_it);
- infos.push_back(*info_it);
- }
- }
- }
-
- return infos;
- }
-};
-
-TEST_F(PackageListTraceRedactorIntegrationTest,
- FindsPackageAndFiltersPackageList) {
- auto result = redactor_.Redact(
- src_trace(), tmp_dir_.AbsolutePath("dst.pftrace"), &context_);
-
- ASSERT_OK(result) << result.message();
-
- tmp_dir_.TrackFile("dst.pftrace");
-
- ASSERT_OK_AND_ASSIGN(auto redacted_buffer,
- ReadRawTrace(tmp_dir_.AbsolutePath("dst.pftrace")));
-
- protos::pbzero::Trace::Decoder redacted_trace(redacted_buffer);
- std::vector<protozero::ConstBytes> infos = GetPackageInfos(redacted_trace);
-
- ASSERT_TRUE(context_.package_uid.has_value());
- ASSERT_EQ(NormalizeUid(context_.package_uid.value()),
- NormalizeUid(kPackageUid));
-
- // It is possible for two packages_list to appear in the trace. The
- // find_package_uid will stop after the first one is found. Package uids are
- // appear as n * 1,000,000 where n is some integer. It is also possible for
- // two packages_list to contain copies of each other - for example
- // "com.Unity.com.unity.multiplayer.samples.coop" appears in both
- // packages_list.
- ASSERT_EQ(infos.size(), 2u);
-
- std::vector<protos::pbzero::PackagesList::PackageInfo::Decoder> decoders;
- decoders.emplace_back(infos[0]);
- decoders.emplace_back(infos[1]);
-
- for (auto& decoder : decoders) {
- ASSERT_TRUE(decoder.has_name());
- ASSERT_EQ(decoder.name().ToStdString(),
- "com.Unity.com.unity.multiplayer.samples.coop");
-
- ASSERT_TRUE(decoder.has_uid());
- ASSERT_EQ(NormalizeUid(decoder.uid()), NormalizeUid(kPackageUid));
- }
-}
-
-// It is possible for multiple packages to share a uid. The names will appears
-// across multiple package lists. The only time the package name appears is in
-// the package list, so there is no way to differentiate these packages (only
-// the uid is used later), so each entry should remain.
-TEST_F(PackageListTraceRedactorIntegrationTest, RetainsAllInstancesOfUid) {
- context_.package_name = "com.google.android.networkstack.tethering";
-
- auto result = redactor_.Redact(
- src_trace(), tmp_dir_.AbsolutePath("dst.pftrace"), &context_);
-
- ASSERT_OK(result) << result.message();
-
- tmp_dir_.TrackFile("dst.pftrace");
-
- ASSERT_OK_AND_ASSIGN(auto redacted_buffer,
- ReadRawTrace(tmp_dir_.AbsolutePath("dst.pftrace")));
-
- protos::pbzero::Trace::Decoder redacted_trace(redacted_buffer);
- std::vector<protozero::ConstBytes> infos = GetPackageInfos(redacted_trace);
-
- ASSERT_EQ(infos.size(), 8u);
-
- std::array<std::string, 8> package_names;
-
- for (size_t i = 0; i < infos.size(); ++i) {
- protos::pbzero::PackagesList::PackageInfo::Decoder info(infos[i]);
- ASSERT_TRUE(info.has_name());
- package_names[i] = info.name().ToStdString();
- }
-
- std::sort(package_names.begin(), package_names.end());
- ASSERT_EQ(package_names[0], "com.google.android.cellbroadcastservice");
- ASSERT_EQ(package_names[1], "com.google.android.cellbroadcastservice");
- ASSERT_EQ(package_names[2], "com.google.android.networkstack");
- ASSERT_EQ(package_names[3], "com.google.android.networkstack");
- ASSERT_EQ(package_names[4],
- "com.google.android.networkstack.permissionconfig");
- ASSERT_EQ(package_names[5],
- "com.google.android.networkstack.permissionconfig");
- ASSERT_EQ(package_names[6], "com.google.android.networkstack.tethering");
- ASSERT_EQ(package_names[7], "com.google.android.networkstack.tethering");
-}
-
-} // namespace
-} // namespace perfetto::trace_redaction
diff --git a/src/traced/probes/ftrace/OWNERS b/src/traced/probes/ftrace/OWNERS
index 66ecb6c..52d5e50 100644
--- a/src/traced/probes/ftrace/OWNERS
+++ b/src/traced/probes/ftrace/OWNERS
@@ -1,5 +1,4 @@
# People knowledgeable with traced_probes <> ftrace integration.
-hjd@google.com
primiano@google.com
rsavitski@google.com
skyostil@google.com
diff --git a/test/cts/OWNERS b/test/cts/OWNERS
index 10fd9fe..0a7edbb 100644
--- a/test/cts/OWNERS
+++ b/test/cts/OWNERS
@@ -1,6 +1,5 @@
# Bug component: 323270
ddiproietto@google.com
-hjd@google.com
lalitm@google.com
primiano@google.com
rsavitski@google.com
diff --git a/test/trace_processor/diff_tests/stdlib/OWNERS b/test/trace_processor/diff_tests/stdlib/OWNERS
index 0479e4b..21e80a4 100644
--- a/test/trace_processor/diff_tests/stdlib/OWNERS
+++ b/test/trace_processor/diff_tests/stdlib/OWNERS
@@ -1,3 +1,3 @@
-# These can't be added inside chrome/ bacause the whole directory is
+# These can't be added inside chrome/ because the whole directory is
# blown away on every import.
per-file chrome/* = file://protos/third_party/CHROMIUM_OWNERS
diff --git a/test/trace_processor/diff_tests/stdlib/chrome/tests_scroll_jank.py b/test/trace_processor/diff_tests/stdlib/chrome/tests_scroll_jank.py
index ae641d4..3f9e4b8 100755
--- a/test/trace_processor/diff_tests/stdlib/chrome/tests_scroll_jank.py
+++ b/test/trace_processor/diff_tests/stdlib/chrome/tests_scroll_jank.py
@@ -40,7 +40,7 @@
def test_chrome_scrolls(self):
return DiffTestBlueprint(
- trace=Path('chrome_scroll_check.py'),
+ trace=DataPath('chrome_input_with_frame_view.pftrace'),
query="""
INCLUDE PERFETTO MODULE chrome.chrome_scrolls;
@@ -55,15 +55,15 @@
""",
out=Csv("""
"id","ts","dur","gesture_scroll_begin_ts","gesture_scroll_end_ts"
- 5678,0,55000000,0,45000000
- 5679,60000000,40000000,60000000,90000000
- 5680,80000000,30000000,80000000,100000000
- 5681,120000000,70000000,120000000,"[NULL]"
+ 4328,1035865535981926,1255745000,1035865535981926,1035866753550926
+ 4471,1035866799527926,1358505000,1035866799527926,1035868108723926
+ 4620,1035868146266926,111786000,1035868146266926,1035868230937926
+ 4652,1035868607429926,1517121000,1035868607429926,1035870086449926
"""))
def test_chrome_scroll_intervals(self):
return DiffTestBlueprint(
- trace=Path('chrome_scroll_check.py'),
+ trace=DataPath('chrome_input_with_frame_view.pftrace'),
query="""
INCLUDE PERFETTO MODULE chrome.chrome_scrolls;
@@ -76,9 +76,9 @@
""",
out=Csv("""
"id","ts","dur"
- 1,0,55000000
- 2,60000000,50000000
- 3,120000000,70000000
+ 1,1035865535981926,1255745000
+ 2,1035866799527926,1458525000
+ 3,1035868607429926,1517121000
"""))
def test_chrome_scroll_input_offsets(self):
@@ -167,10 +167,10 @@
""",
out=Csv("""
"scroll_id","missed_vsyncs","frame_count","presented_frame_count","janky_frame_count","janky_frame_percent"
- 4328,"[NULL]",109,110,0,0.000000
- 4471,"[NULL]",117,118,0,0.000000
- 4620,"[NULL]",5,4,0,0.000000
- 4652,1,122,122,1,0.820000
+ 4328,"[NULL]",110,110,0,0.000000
+ 4471,"[NULL]",118,118,0,0.000000
+ 4620,"[NULL]",6,4,0,0.000000
+ 4652,1,123,122,1,0.820000
"""))
def test_chrome_scroll_jank_intervals_v3(self):
diff --git a/test/vts/OWNERS b/test/vts/OWNERS
index 10fd9fe..0a7edbb 100644
--- a/test/vts/OWNERS
+++ b/test/vts/OWNERS
@@ -1,6 +1,5 @@
# Bug component: 323270
ddiproietto@google.com
-hjd@google.com
lalitm@google.com
primiano@google.com
rsavitski@google.com
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index c8db4ec..d71b0dc 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -121,13 +121,19 @@
# Proto target groups which will be made public.
proto_groups = {
- 'trace': [
- '//protos/perfetto/trace:non_minimal_source_set',
- '//protos/perfetto/trace:minimal_source_set'
- ],
- 'config': [
- '//protos/perfetto/config:source_set',
- ],
+ 'trace': {
+ 'types': ['filegroup', 'lite'],
+ 'targets': [
+ '//protos/perfetto/trace:non_minimal_source_set',
+ '//protos/perfetto/trace:minimal_source_set',
+ ]
+ },
+ 'config': {
+ 'types': ['lite'],
+ 'targets': [
+ '//protos/perfetto/config:source_set',
+ ]
+ },
}
needs_libfts = [
@@ -956,23 +962,34 @@
def create_proto_group_modules(blueprint, gn: GnParser, module_name: str,
- target_names):
- # TODO(lalitm): today, we're only adding a Java lite module because that's
- # the only one used in practice. In the future, if we need other target types
- # (e.g. C++, Java full etc.) add them here.
- bp_module_name = label_to_module_name(module_name) + '_java_protos'
- module = Module('java_library', bp_module_name, bp_module_name)
- module.comment = f'''GN: [{', '.join(target_names)}]'''
- module.proto = {'type': 'lite', 'canonical_path_from_root': False}
+ group):
+ target_names = group['targets']
+ module_types = group['types']
+ module_sources = set()
for name in target_names:
target = gn.get_target(name)
- module.srcs.update(gn_utils.label_to_path(src) for src in target.sources)
+ module_sources.update(gn_utils.label_to_path(src) for src in target.sources)
for dep_label in target.transitive_proto_deps():
dep = gn.get_target(dep_label.name)
- module.srcs.update(gn_utils.label_to_path(src) for src in dep.sources)
+ module_sources.update(gn_utils.label_to_path(src) for src in dep.sources)
- blueprint.add_module(module)
+ for type in module_types:
+ if type == 'filegroup':
+ name = label_to_module_name(module_name) + '_filegroup_proto'
+ module = Module('filegroup', name, name)
+ module.comment = f'''GN: [{', '.join(target_names)}]'''
+ module.srcs = module_sources
+ blueprint.add_module(module)
+ elif type == 'lite':
+ name = label_to_module_name(module_name) + '_java_protos'
+ module = Module('java_library', name, name)
+ module.comment = f'''GN: [{', '.join(target_names)}]'''
+ module.proto = {'type': 'lite', 'canonical_path_from_root': False}
+ module.srcs = module_sources
+ blueprint.add_module(module)
+ else:
+ raise Error('Unhandled proto group type: {}'.format(group.type))
def _get_cflags(target: GnParser.Target):
@@ -1228,8 +1245,8 @@
# checker = gn_utils.ODRChecker(gn, target_name)
# Add any proto groups to the blueprint.
- for l_name, t_names in proto_groups.items():
- create_proto_group_modules(blueprint, gn, l_name, t_names)
+ for name, group in proto_groups.items():
+ create_proto_group_modules(blueprint, gn, name, group)
output = [
"""// Copyright (C) 2017 The Android Open Source Project
diff --git a/ui/OWNERS b/ui/OWNERS
index aaf587f..d6b4b3d 100644
--- a/ui/OWNERS
+++ b/ui/OWNERS
@@ -1,4 +1,3 @@
-hjd@google.com
primiano@google.com
stevegolton@google.com
diff --git a/ui/release/OWNERS b/ui/release/OWNERS
index 418a82a..4108764 100644
--- a/ui/release/OWNERS
+++ b/ui/release/OWNERS
@@ -1,6 +1,5 @@
set noparent
eseckler@google.com
-hjd@google.com
lalitm@google.com
primiano@google.com
skyostil@google.com
diff --git a/ui/release/channels.json b/ui/release/channels.json
index 5f4dd4d..c87709e 100644
--- a/ui/release/channels.json
+++ b/ui/release/channels.json
@@ -6,7 +6,7 @@
},
{
"name": "canary",
- "rev": "58439240cbad83689a1fbafd8234a379a56be7c1"
+ "rev": "9945c86178de704ff44bef7f64c020ff79aedd28"
},
{
"name": "autopush",
diff --git a/ui/src/assets/viewer_page.scss b/ui/src/assets/viewer_page.scss
index c090dc9..690231e 100644
--- a/ui/src/assets/viewer_page.scss
+++ b/ui/src/assets/viewer_page.scss
@@ -42,7 +42,7 @@
overflow: auto;
}
- .header {
+ .pf-timeline-header {
display: flex;
flex-direction: row;
box-shadow: 1px 3px 15px rgba(23, 32, 44, 0.3);
diff --git a/ui/src/assets/widgets/button.scss b/ui/src/assets/widgets/button.scss
index a5e8f9a..65f6a56 100644
--- a/ui/src/assets/widgets/button.scss
+++ b/ui/src/assets/widgets/button.scss
@@ -18,8 +18,6 @@
font-family: $pf-font;
line-height: 1;
user-select: none;
- color: $pf-primary-foreground;
- background: $pf-primary-background;
transition: background $pf-anim-timing, box-shadow $pf-anim-timing;
border-radius: $pf-border-radius;
padding: 4px 8px;
@@ -42,45 +40,47 @@
line-height: inherit;
}
- &:hover {
- background: $pf-primary-background-hover;
- }
-
- &:active,
- &.pf-active {
- transition: none;
- background: $pf-primary-background-active;
- box-shadow: inset 1px 1px 4px #00000040;
- }
-
&:focus-visible {
@include focus;
}
+ background: $pf-minimal-background;
+ color: inherit;
+
+ &:hover {
+ background: $pf-minimal-background-hover;
+ }
+
+ &:active,
+ &.pf-active {
+ background: $pf-minimal-background-active;
+ }
+
&[disabled] {
- background: $pf-primary-background-disabled;
- color: $pf-primary-foreground-disabled;
- box-shadow: none;
+ color: $pf-minimal-foreground-disabled;
+ background: $pf-minimal-background-disabled;
cursor: not-allowed;
}
// Remove default background in minimal mode, showing only the text
- &.pf-minimal {
- background: $pf-minimal-background;
- color: inherit;
+ &.pf-intent-primary {
+ color: $pf-primary-foreground;
+ background: $pf-primary-background;
&:hover {
- background: $pf-minimal-background-hover;
+ background: $pf-primary-background-hover;
}
&:active,
&.pf-active {
- background: $pf-minimal-background-active;
+ transition: none;
+ background: $pf-primary-background-active;
+ box-shadow: inset 1px 1px 4px #00000040;
}
-
&[disabled] {
- color: $pf-minimal-foreground-disabled;
- background: $pf-minimal-background-disabled;
+ background: $pf-primary-background-disabled;
+ color: $pf-primary-foreground-disabled;
+ box-shadow: none;
cursor: not-allowed;
}
}
diff --git a/ui/src/base/logging.ts b/ui/src/base/logging.ts
index 74cbe44..04e0bc7 100644
--- a/ui/src/base/logging.ts
+++ b/ui/src/base/logging.ts
@@ -134,6 +134,6 @@
// 2) A compile time check where typescript asserts that the value passed can be
// cast to the "never" type.
// This is useful for ensuring we exhastively check union types.
-export function assertUnreachable(value: never) {
+export function assertUnreachable(value: never): never {
throw new Error(`This code should not be reachable ${value as unknown}`);
}
diff --git a/ui/src/common/recordingV2/recording_config_utils.ts b/ui/src/common/recordingV2/recording_config_utils.ts
index 334ad25..133d606 100644
--- a/ui/src/common/recordingV2/recording_config_utils.ts
+++ b/ui/src/common/recordingV2/recording_config_utils.ts
@@ -769,7 +769,7 @@
) {
const ds = new TraceConfig.DataSource();
ds.config = new DataSourceConfig();
- ds.config.name = 'windows.etw';
+ ds.config.name = 'org.chromium.etw_system';
ds.config.etwConfig = new EtwConfig();
const kernelFlags: EtwConfig.KernelFlag[] = [];
diff --git a/ui/src/common/thread_state.ts b/ui/src/common/thread_state.ts
index 6ef6188..d94625c 100644
--- a/ui/src/common/thread_state.ts
+++ b/ui/src/common/thread_state.ts
@@ -34,9 +34,18 @@
ioWait: boolean | undefined = undefined,
) {
if (state === undefined) return '';
- if (state === 'Running') {
- return state;
+
+ // Self describing states
+ switch (state) {
+ case 'Running':
+ case 'Initialized':
+ case 'Deferred Ready':
+ case 'Transition':
+ case 'Stand By':
+ case 'Waiting':
+ return state;
}
+
if (state === null) {
return 'Unknown';
}
diff --git a/ui/src/common/track_cache.ts b/ui/src/common/track_cache.ts
index 3b2eb41..5d05a13 100644
--- a/ui/src/common/track_cache.ts
+++ b/ui/src/common/track_cache.ts
@@ -180,6 +180,7 @@
}
enum TrackFSMState {
+ NotCreated = 'not_created',
Creating = 'creating',
Ready = 'ready',
UpdatePending = 'update_pending',
@@ -200,20 +201,22 @@
constructor(
public track: Track,
public desc: TrackDescriptor,
- ctx: TrackContext,
+ private readonly ctx: TrackContext,
) {
- this.state = TrackFSMState.Creating;
- const result = this.track.onCreate?.(ctx);
- Promise.resolve(result)
- .then(() => this.onTrackCreated())
- .catch((e) => {
- this.error = e;
- this.state = TrackFSMState.Error;
- });
+ this.state = TrackFSMState.NotCreated;
}
update(): void {
switch (this.state) {
+ case TrackFSMState.NotCreated:
+ Promise.resolve(this.track.onCreate?.(this.ctx))
+ .then(() => this.onTrackCreated())
+ .catch((e) => {
+ this.error = e;
+ this.state = TrackFSMState.Error;
+ });
+ this.state = TrackFSMState.Creating;
+ break;
case TrackFSMState.Creating:
case TrackFSMState.Updating:
this.state = TrackFSMState.UpdatePending;
@@ -240,6 +243,10 @@
destroy(): void {
switch (this.state) {
+ case TrackFSMState.NotCreated:
+ // Nothing to do
+ this.state = TrackFSMState.Destroyed;
+ break;
case TrackFSMState.Ready:
// Don't bother awaiting this as the track can no longer be used.
Promise.resolve(this.track.onDestroy?.()).catch(() => {
@@ -267,6 +274,7 @@
this.track.onDestroy?.();
this.state = TrackFSMState.Destroyed;
break;
+ case TrackFSMState.Creating:
case TrackFSMState.UpdatePending:
const result = this.track.onUpdate?.();
Promise.resolve(result)
@@ -277,9 +285,6 @@
});
this.state = TrackFSMState.Updating;
break;
- case TrackFSMState.Creating:
- this.state = TrackFSMState.Ready;
- break;
case TrackFSMState.Error:
break;
default:
diff --git a/ui/src/common/track_cache_unittest.ts b/ui/src/common/track_cache_unittest.ts
index 2be2d55..599a748 100644
--- a/ui/src/common/track_cache_unittest.ts
+++ b/ui/src/common/track_cache_unittest.ts
@@ -63,8 +63,10 @@
it('reuses tracks', async () => {
const first = trackCache.resolveTrack('foo', td);
trackCache.flushOldTracks();
+ first.update();
const second = trackCache.resolveTrack('foo', td);
trackCache.flushOldTracks();
+ second.update();
// Ensure onCreate only called once
expect(track.onCreate).toHaveBeenCalledTimes(1);
@@ -72,7 +74,8 @@
});
it('destroys tracks', async () => {
- trackCache.resolveTrack('foo', td);
+ const t = trackCache.resolveTrack('foo', td);
+ t.update();
// Double flush should destroy all tracks
trackCache.flushOldTracks();
diff --git a/ui/src/frontend/aggregation_tab.ts b/ui/src/frontend/aggregation_tab.ts
index c6c46f6..d24fc1d 100644
--- a/ui/src/frontend/aggregation_tab.ts
+++ b/ui/src/frontend/aggregation_tab.ts
@@ -109,7 +109,6 @@
key,
label: name,
active: currentViewKey === key,
- minimal: true,
});
});
diff --git a/ui/src/frontend/app.ts b/ui/src/frontend/app.ts
index 4bed3fc..0f11c59 100644
--- a/ui/src/frontend/app.ts
+++ b/ui/src/frontend/app.ts
@@ -804,6 +804,9 @@
this.addRecentCommand(key);
cmdMgr.runCommand(key);
},
+ onGoBack: () => {
+ this.enterSearchMode(false);
+ },
});
}
@@ -822,6 +825,7 @@
placeholder: ph,
inputRef: App.OMNIBOX_INPUT_REF,
extraClasses: 'query-mode',
+
onInput: (value) => {
this.queryText = value;
raf.scheduleFullRedraw();
@@ -842,6 +846,9 @@
this.enterSearchMode(false);
raf.scheduleFullRedraw();
},
+ onGoBack: () => {
+ this.enterSearchMode(false);
+ },
});
}
diff --git a/ui/src/frontend/base_counter_track.ts b/ui/src/frontend/base_counter_track.ts
index 3fe5c71..9996782 100644
--- a/ui/src/frontend/base_counter_track.ts
+++ b/ui/src/frontend/base_counter_track.ts
@@ -450,7 +450,7 @@
return m(
PopupMenu2,
{
- trigger: m(Button, {icon: 'show_chart', minimal: true, compact: true}),
+ trigger: m(Button, {icon: 'show_chart', compact: true}),
},
this.getCounterContextMenuItems(),
);
@@ -963,6 +963,6 @@
}
get unit(): string {
- return this.getCounterOptions().unit ?? '?';
+ return this.getCounterOptions().unit ?? '';
}
}
diff --git a/ui/src/frontend/chrome_slice_details_tab.ts b/ui/src/frontend/chrome_slice_details_tab.ts
index 90471ed..f42d4b6 100644
--- a/ui/src/frontend/chrome_slice_details_tab.ts
+++ b/ui/src/frontend/chrome_slice_details_tab.ts
@@ -399,7 +399,6 @@
const contextMenuItems = getSliceContextMenuItems(sliceInfo);
if (contextMenuItems.length > 0) {
const trigger = m(Button, {
- minimal: true,
compact: true,
label: 'Contextual Options',
rightIcon: Icons.ContextMenu,
diff --git a/ui/src/frontend/close_track_button.ts b/ui/src/frontend/close_track_button.ts
index e7b667b..1b0fd91 100644
--- a/ui/src/frontend/close_track_button.ts
+++ b/ui/src/frontend/close_track_button.ts
@@ -34,7 +34,6 @@
},
icon: Icons.Close,
title: 'Close',
- minimal: true,
compact: true,
});
}
diff --git a/ui/src/frontend/drag_handle.ts b/ui/src/frontend/drag_handle.ts
index 70aea03..dd43077 100644
--- a/ui/src/frontend/drag_handle.ts
+++ b/ui/src/frontend/drag_handle.ts
@@ -209,7 +209,6 @@
onTabClose(key);
event.preventDefault();
},
- minimal: true,
compact: true,
icon: 'close',
}),
@@ -237,7 +236,6 @@
title: 'Open fullscreen',
disabled: this.isFullscreen,
icon: 'vertical_align_top',
- minimal: true,
compact: true,
}),
m(Button, {
@@ -246,7 +244,6 @@
},
title,
icon,
- minimal: true,
compact: true,
}),
),
@@ -258,7 +255,6 @@
PopupMenu2,
{
trigger: m(Button, {
- minimal: true,
compact: true,
icon: 'more_vert',
disabled: entries.length === 0,
diff --git a/ui/src/frontend/flamegraph_panel.ts b/ui/src/frontend/flamegraph_panel.ts
index 0f4cba2..6e6f550 100644
--- a/ui/src/frontend/flamegraph_panel.ts
+++ b/ui/src/frontend/flamegraph_panel.ts
@@ -42,6 +42,7 @@
import {ButtonBar} from '../widgets/button';
import {DurationWidget} from './widgets/duration';
import {DetailsShell} from '../widgets/details_shell';
+import {Intent} from '../widgets/common';
const HEADER_HEIGHT = 30;
@@ -143,6 +144,7 @@
this.profileType === ProfileType.JAVA_HEAP_SAMPLES) &&
m(Button, {
icon: 'file_download',
+ intent: Intent.Primary,
onclick: () => {
this.downloadPprof();
},
@@ -416,7 +418,6 @@
return m(Button, {
label: text,
active,
- minimal: true,
onclick: () => {
globals.dispatch(Actions.changeViewFlamegraphState({viewingOption}));
},
diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts
index 85cbe07..c583e2d 100644
--- a/ui/src/frontend/notes_panel.ts
+++ b/ui/src/frontend/notes_panel.ts
@@ -108,7 +108,6 @@
},
title: allCollapsed ? 'Expand all' : 'Collapse all',
icon: allCollapsed ? 'unfold_more' : 'unfold_less',
- minimal: true,
compact: true,
}),
m(Button, {
@@ -118,7 +117,6 @@
},
title: 'Clear all pinned tracks',
icon: 'clear_all',
- minimal: true,
compact: true,
}),
),
@@ -394,7 +392,6 @@
m(Button, {
label: 'Remove',
icon: Icons.Delete,
- minimal: true,
onclick: () => {
globals.dispatch(Actions.removeNote({id: this.config.id}));
raf.scheduleFullRedraw();
diff --git a/ui/src/frontend/omnibox.ts b/ui/src/frontend/omnibox.ts
index b0f0416..16ada06 100644
--- a/ui/src/frontend/omnibox.ts
+++ b/ui/src/frontend/omnibox.ts
@@ -123,6 +123,9 @@
// Called when the user expresses the intent to "execute" the thing.
onSubmit?: (value: string, mod: boolean, shift: boolean) => void;
+ // Called when the user hits backspace when the field is empty.
+ onGoBack?: () => void;
+
// When true, disable and grey-out the omnibox's input.
readonly?: boolean;
@@ -160,6 +163,7 @@
extraClasses,
onInput = () => {},
onSubmit = () => {},
+ onGoBack = () => {},
inputRef = 'omnibox',
options,
closeOnSubmit = false,
@@ -190,7 +194,7 @@
},
onkeydown: (e: KeyboardEvent) => {
if (e.key === 'Backspace' && value === '') {
- this.close(attrs);
+ onGoBack();
} else if (e.key === 'Escape') {
e.preventDefault();
this.close(attrs);
diff --git a/ui/src/frontend/plugins_page.ts b/ui/src/frontend/plugins_page.ts
index 19c0739..ed2b2f5 100644
--- a/ui/src/frontend/plugins_page.ts
+++ b/ui/src/frontend/plugins_page.ts
@@ -22,6 +22,7 @@
import {PluginDescriptor} from '../public';
import {createPage} from './pages';
import {defaultPlugins} from '../core/default_plugins';
+import {Intent} from '../widgets/common';
export const PluginsPage = createPage({
view() {
@@ -31,7 +32,7 @@
m(
'.pf-plugins-topbar',
m(Button, {
- minimal: false,
+ intent: Intent.Primary,
label: 'Disable All',
onclick: async () => {
for (const plugin of pluginRegistry.values()) {
@@ -41,7 +42,7 @@
},
}),
m(Button, {
- minimal: false,
+ intent: Intent.Primary,
label: 'Enable All',
onclick: async () => {
for (const plugin of pluginRegistry.values()) {
@@ -51,7 +52,7 @@
},
}),
m(Button, {
- minimal: false,
+ intent: Intent.Primary,
label: 'Restore Defaults',
onclick: async () => {
await pluginManager.restoreDefaults(true);
@@ -95,6 +96,7 @@
: m('.pf-tag.pf-inactive', 'Inactive'),
m(Button, {
label: isActive ? 'Disable' : 'Enable',
+ intent: Intent.Primary,
onclick: async () => {
if (isActive) {
await pluginManager.disablePlugin(pluginId, true);
diff --git a/ui/src/frontend/query_result_tab.ts b/ui/src/frontend/query_result_tab.ts
index f7fbf62..23b5148 100644
--- a/ui/src/frontend/query_result_tab.ts
+++ b/ui/src/frontend/query_result_tab.ts
@@ -130,7 +130,7 @@
: m(
PopupMenu2,
{
- trigger: m(Button, {label: 'Show debug track', minimal: true}),
+ trigger: m(Button, {label: 'Show debug track'}),
popupPosition: PopupPosition.Top,
},
m(AddDebugTrackMenu, {
diff --git a/ui/src/frontend/query_table.ts b/ui/src/frontend/query_table.ts
index 4affa45..e9bbce9 100644
--- a/ui/src/frontend/query_table.ts
+++ b/ui/src/frontend/query_table.ts
@@ -249,7 +249,6 @@
contextButtons,
m(Button, {
label: 'Copy query',
- minimal: true,
onclick: () => {
copyToClipboard(query);
},
@@ -258,7 +257,6 @@
resp.error === undefined &&
m(Button, {
label: 'Copy result (.tsv)',
- minimal: true,
onclick: () => {
queryResponseToClipboard(resp);
},
diff --git a/ui/src/frontend/sql_table/tab.ts b/ui/src/frontend/sql_table/tab.ts
index 01c87af..ea173a0 100644
--- a/ui/src/frontend/sql_table/tab.ts
+++ b/ui/src/frontend/sql_table/tab.ts
@@ -94,13 +94,11 @@
icon: Icons.GoBack,
disabled: !this.state.canGoBack(),
onclick: () => this.state.goBack(),
- minimal: true,
}),
m(Button, {
icon: Icons.GoForward,
disabled: !this.state.canGoForward(),
onclick: () => this.state.goForward(),
- minimal: true,
}),
];
const {selectStatement, columns} = this.state.buildSqlSelectStatement();
diff --git a/ui/src/frontend/thread_state_tab.ts b/ui/src/frontend/thread_state_tab.ts
index 26dcb57..fac6b8a 100644
--- a/ui/src/frontend/thread_state_tab.ts
+++ b/ui/src/frontend/thread_state_tab.ts
@@ -24,6 +24,7 @@
import {Section} from '../widgets/section';
import {SqlRef} from '../widgets/sql_ref';
import {Tree, TreeNode} from '../widgets/tree';
+import {Intent} from '../widgets/common';
import {BottomTab, NewBottomTabArgs} from './bottom_tab';
import {SchedSqlId, ThreadStateSqlId} from './sql_types';
@@ -319,6 +320,7 @@
),
m(Button, {
label: 'Critical path lite',
+ intent: Intent.Primary,
onclick: () =>
runQuery(
`INCLUDE PERFETTO MODULE sched.thread_executing_span;`,
@@ -355,6 +357,7 @@
}),
m(Button, {
label: 'Critical path',
+ intent: Intent.Primary,
onclick: () =>
runQuery(
`INCLUDE PERFETTO MODULE sched.thread_executing_span_with_slice;`,
diff --git a/ui/src/frontend/track_group_panel.ts b/ui/src/frontend/track_group_panel.ts
index 1e35329..ec9a43a 100644
--- a/ui/src/frontend/track_group_panel.ts
+++ b/ui/src/frontend/track_group_panel.ts
@@ -150,7 +150,6 @@
e.stopPropagation();
},
icon: checkBox,
- minimal: true,
compact: true,
}),
),
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index 59c9857..d2cc66b 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -39,6 +39,7 @@
import {getLegacySelection} from '../common/state';
import {CloseTrackButton} from './close_track_button';
import {exists} from '../base/utils';
+import {Intent} from '../widgets/common';
function getTitleSize(title: string): string | undefined {
const length = title.length;
@@ -99,7 +100,6 @@
{
trigger: m(Button, {
icon: Icons.Crashed,
- minimal: true,
}),
},
this.renderErrorMessage(attrs.error),
@@ -112,6 +112,7 @@
'This track has crashed',
m(Button, {
label: 'Re-raise exception',
+ intent: Intent.Primary,
className: Popup.DISMISS_POPUP_GROUP_CLASS,
onclick: () => {
throw error;
@@ -190,7 +191,6 @@
icon: Icons.Pin,
iconFilled: pinned,
title: pinned ? 'Unpin' : 'Pin to top',
- minimal: true,
compact: true,
}),
currentSelection !== null && currentSelection.kind === 'AREA'
@@ -204,7 +204,6 @@
);
e.stopPropagation();
},
- minimal: true,
compact: true,
icon: isSelected(attrs.trackKey)
? Icons.Checkbox
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 73decc9..b599dc7 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -293,7 +293,7 @@
},
},
m(
- '.header',
+ '.pf-timeline-header',
m(PanelContainer, {
className: 'header-panel-container',
panels: [
diff --git a/ui/src/frontend/widgets_page.ts b/ui/src/frontend/widgets_page.ts
index 2792b7b..ea80972 100644
--- a/ui/src/frontend/widgets_page.ts
+++ b/ui/src/frontend/widgets_page.ts
@@ -49,6 +49,7 @@
import {PopupMenuButton} from './popup_menu';
import {TableShowcase} from './tables/table_showcase';
import {TreeTable, TreeTableAttrs} from './widgets/treetable';
+import {Intent} from '../widgets/common';
const DATA_ENGLISH_LETTER_FREQUENCY = {
table: [
@@ -290,6 +291,7 @@
return [
m(Button, {
label: 'Toggle Portal',
+ intent: Intent.Primary,
onclick: () => {
portalOpen = !portalOpen;
raf.scheduleFullRedraw();
@@ -586,7 +588,7 @@
icon: true,
rightIcon: false,
disabled: false,
- minimal: false,
+ intent: new EnumOption(Intent.None, Object.values(Intent)),
active: false,
compact: false,
loading: false,
diff --git a/ui/src/plugins/dev.perfetto.BookmarkletApi/OWNERS b/ui/src/plugins/dev.perfetto.BookmarkletApi/OWNERS
index 888f192..e159207 100644
--- a/ui/src/plugins/dev.perfetto.BookmarkletApi/OWNERS
+++ b/ui/src/plugins/dev.perfetto.BookmarkletApi/OWNERS
@@ -1,2 +1 @@
-hjd@google.com
stevegolton@google.com
diff --git a/ui/src/plugins/dev.perfetto.Chaos/OWNERS b/ui/src/plugins/dev.perfetto.Chaos/OWNERS
index 9ee9fce..e159207 100644
--- a/ui/src/plugins/dev.perfetto.Chaos/OWNERS
+++ b/ui/src/plugins/dev.perfetto.Chaos/OWNERS
@@ -1 +1 @@
-hjd@google.com
+stevegolton@google.com
diff --git a/ui/src/public/index.ts b/ui/src/public/index.ts
index e51d5d5..a8d2949 100644
--- a/ui/src/public/index.ts
+++ b/ui/src/public/index.ts
@@ -177,10 +177,15 @@
export interface Track {
/**
- * Optional: Called when the track is first materialized on the timeline.
+ * Optional: Called once before onUpdate is first called.
+ *
* If this function returns a Promise, this promise is awaited before onUpdate
* or onDestroy is called. Any calls made to these functions in the meantime
* will be queued up and the hook will be called later once onCreate returns.
+ *
+ * Exactly when this hook is called is left purposely undefined. The only
+ * guarantee is that it will be called once before onUpdate is first called.
+ *
* @param ctx Our track context object.
*/
onCreate?(ctx: TrackContext): Promise<void> | void;
diff --git a/ui/src/tracks/android_log/logs_panel.ts b/ui/src/tracks/android_log/logs_panel.ts
index 1a8d233..51e0889 100644
--- a/ui/src/tracks/android_log/logs_panel.ts
+++ b/ui/src/tracks/android_log/logs_panel.ts
@@ -30,6 +30,7 @@
import {Select} from '../../widgets/select';
import {Button} from '../../widgets/button';
import {TextInput} from '../../widgets/text_input';
+import {Intent} from '../../widgets/common';
const ROW_H = 20;
@@ -285,6 +286,7 @@
label: attrs.name,
rightIcon: 'close',
onclick: () => attrs.removeTag(attrs.name),
+ intent: Intent.Primary,
});
}
}
@@ -371,7 +373,6 @@
icon,
title: tooltip,
disabled: attrs.disabled,
- minimal: true,
onclick: attrs.onClick,
});
}
diff --git a/ui/src/tracks/counter/index.ts b/ui/src/tracks/counter/index.ts
index a459c8a..5fdf938 100644
--- a/ui/src/tracks/counter/index.ts
+++ b/ui/src/tracks/counter/index.ts
@@ -136,15 +136,21 @@
const time = visibleTimeScale.pxToHpTime(x).toTime('floor');
const query = `
+ WITH X AS (
+ SELECT
+ id,
+ ts AS leftTs,
+ LEAD(ts) OVER (ORDER BY ts) AS rightTs
+ FROM counter
+ WHERE track_id = ${this.trackId}
+ ORDER BY ts
+ )
SELECT
id,
- ts as leftTs,
- min(ts) OVER (ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) as rightTs
- FROM ${this.rootTable}
- WHERE
- track_id = ${this.trackId} AND
- ts < ${time}
- ORDER BY ts DESC
+ leftTs,
+ rightTs
+ FROM X
+ WHERE rightTs > ${time}
LIMIT 1
`;
@@ -152,7 +158,7 @@
const it = result.iter({
id: NUM,
leftTs: LONG,
- rightTs: LONG,
+ rightTs: LONG_NULL,
});
if (!it.valid()) {
return;
@@ -160,7 +166,11 @@
const trackKey = this.trackKey;
const id = it.id;
const leftTs = Time.fromRaw(it.leftTs);
- const rightTs = Time.fromRaw(it.rightTs);
+
+ // TODO(stevegolton): Don't try to guess times and durations here, make it
+ // obvious to the user that this counter sample has no duration as it's
+ // the last one in the series
+ const rightTs = Time.fromRaw(it.rightTs ?? leftTs);
globals.makeSelection(
Actions.selectCounter({
diff --git a/ui/src/tracks/ftrace/ftrace_explorer.ts b/ui/src/tracks/ftrace/ftrace_explorer.ts
index 6884d70..9481b86 100644
--- a/ui/src/tracks/ftrace/ftrace_explorer.ts
+++ b/ui/src/tracks/ftrace/ftrace_explorer.ts
@@ -206,7 +206,6 @@
if (attrs.cache.state !== 'valid') {
return m(Button, {
label: 'Filter',
- minimal: true,
disabled: true,
loading: true,
});
@@ -225,7 +224,6 @@
return m(PopupMultiSelect, {
label: 'Filter',
- minimal: true,
icon: 'filter_list_alt',
popupPosition: PopupPosition.Top,
options,
diff --git a/ui/src/tracks/visualised_args/index.ts b/ui/src/tracks/visualised_args/index.ts
index d2ede0c..9e34de3 100644
--- a/ui/src/tracks/visualised_args/index.ts
+++ b/ui/src/tracks/visualised_args/index.ts
@@ -100,7 +100,6 @@
},
icon: Icons.Close,
title: 'Close',
- minimal: true,
compact: true,
});
}
diff --git a/ui/src/widgets/button.ts b/ui/src/widgets/button.ts
index 276b2f4..6f6a8c0 100644
--- a/ui/src/widgets/button.ts
+++ b/ui/src/widgets/button.ts
@@ -16,7 +16,7 @@
import {classNames} from '../base/classnames';
-import {HTMLAttrs, HTMLButtonAttrs} from './common';
+import {HTMLAttrs, HTMLButtonAttrs, Intent, classForIntent} from './common';
import {Icon} from './icon';
import {Popup} from './popup';
import {Spinner} from './spinner';
@@ -31,9 +31,6 @@
// Use minimal padding, reducing the overall size of the button by a few px.
// Defaults to false.
compact?: boolean;
- // Reduces button decorations.
- // Defaults to false.
- minimal?: boolean;
// Optional right icon.
rightIcon?: string;
// List of space separated class names forwarded to the icon.
@@ -47,6 +44,9 @@
// Whether to use a filled icon
// Defaults to false;
iconFilled?: boolean;
+ // Indicate button colouring by intent.
+ // Defaults to undefined aka "None"
+ intent?: Intent;
}
interface IconButtonAttrs extends CommonAttrs {
@@ -69,11 +69,11 @@
icon,
active,
compact,
- minimal,
rightIcon,
className,
dismissPopup,
iconFilled,
+ intent = Intent.None,
...htmlAttrs
} = attrs;
@@ -82,7 +82,7 @@
const classes = classNames(
active && 'pf-active',
compact && 'pf-compact',
- minimal && 'pf-minimal',
+ classForIntent(intent),
icon && !label && 'pf-icon-only',
dismissPopup && Popup.DISMISS_POPUP_GROUP_CLASS,
className,
diff --git a/ui/src/widgets/common.ts b/ui/src/widgets/common.ts
index 2498310..61352fa 100644
--- a/ui/src/widgets/common.ts
+++ b/ui/src/widgets/common.ts
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {assertUnreachable} from '../base/logging';
+
// This file contains interfaces for attributes for various HTML elements.
// They are typically used by widgets which pass attributes down to their
// internal child, to provide a type-safe interface to users of those widgets.
@@ -59,3 +61,19 @@
export interface HTMLLabelAttrs extends HTMLAttrs {
for?: string;
}
+
+export enum Intent {
+ None = 'none',
+ Primary = 'primary',
+}
+
+export function classForIntent(intent: Intent): string | undefined {
+ switch (intent) {
+ case Intent.None:
+ return undefined;
+ case Intent.Primary:
+ return 'pf-intent-primary';
+ default:
+ return assertUnreachable(intent);
+ }
+}
diff --git a/ui/src/widgets/form.ts b/ui/src/widgets/form.ts
index fbfaae6..8105f6d 100644
--- a/ui/src/widgets/form.ts
+++ b/ui/src/widgets/form.ts
@@ -17,6 +17,7 @@
import {Button} from './button';
import {HTMLAttrs, HTMLLabelAttrs} from './common';
import {Popup} from './popup';
+import {Intent} from '../widgets/common';
export interface FormAttrs extends HTMLAttrs {
// Text to show on the "submit" button.
@@ -73,6 +74,7 @@
label: submitLabel,
rightIcon: submitIcon,
className: Popup.DISMISS_POPUP_GROUP_CLASS,
+ intent: Intent.Primary,
onclick: (e: Event) => {
preventDefault && e.preventDefault();
onSubmit();
@@ -84,13 +86,11 @@
type: 'button',
label: cancelLabel,
className: Popup.DISMISS_POPUP_GROUP_CLASS,
- minimal: true,
}),
// This reset button just clears the form.
resetLabel &&
m(Button, {
label: resetLabel,
- minimal: true,
type: 'reset',
}),
),
diff --git a/ui/src/widgets/multiselect.ts b/ui/src/widgets/multiselect.ts
index edff807..9756dc7 100644
--- a/ui/src/widgets/multiselect.ts
+++ b/ui/src/widgets/multiselect.ts
@@ -22,6 +22,7 @@
import {Popup, PopupPosition} from './popup';
import {scheduleFullRedraw} from './raf';
import {TextInput} from './text_input';
+import {Intent} from './common';
export interface Option {
// The ID is used to indentify this option, and is used in callbacks.
@@ -46,7 +47,7 @@
}
export type PopupMultiSelectAttrs = MultiSelectAttrs & {
- minimal?: boolean;
+ intent?: Intent;
compact?: boolean;
icon?: string;
label: string;
@@ -106,7 +107,6 @@
label:
this.searchText === '' ? 'Clear All' : 'Clear Filtered',
icon: Icons.Deselect,
- minimal: true,
onclick: () => {
const diffs = options
.filter(({checked}) => checked)
@@ -134,7 +134,6 @@
label:
this.searchText === '' ? 'Select All' : 'Select Filtered',
icon: Icons.SelectAll,
- minimal: true,
compact: true,
onclick: () => {
const diffs = options
@@ -148,7 +147,6 @@
m(Button, {
label: this.searchText === '' ? 'Clear All' : 'Clear Filtered',
icon: Icons.Deselect,
- minimal: true,
compact: true,
onclick: () => {
const diffs = options
@@ -193,7 +191,6 @@
},
label: '',
icon: 'close',
- minimal: true,
});
} else {
return null;
@@ -225,7 +222,7 @@
implements m.ClassComponent<PopupMultiSelectAttrs>
{
view({attrs}: m.CVnode<PopupMultiSelectAttrs>) {
- const {icon, popupPosition = PopupPosition.Auto, minimal, compact} = attrs;
+ const {icon, popupPosition = PopupPosition.Auto, intent, compact} = attrs;
return m(
Popup,
@@ -233,7 +230,7 @@
trigger: m(Button, {
label: this.labelText(attrs),
icon,
- minimal,
+ intent,
compact,
}),
position: popupPosition,