Merge "tp: migrate linux device tracks to using InternTrack" into main
diff --git a/CHANGELOG b/CHANGELOG
index e6b841e..89fd78b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,7 +2,9 @@
   Tracing service and probes:
     *
   SQL Standard library:
-    *
+    * Removed the `linux_device_track` table.  Runtime power management tracks
+      in this table now can be found in the `track` table with `classification`
+      `linux_rpm`.
   Trace Processor:
     *
   UI:
diff --git a/src/trace_processor/importers/common/track_classification.h b/src/trace_processor/importers/common/track_classification.h
index c4fbd9c..eb2d92d 100644
--- a/src/trace_processor/importers/common/track_classification.h
+++ b/src/trace_processor/importers/common/track_classification.h
@@ -51,8 +51,8 @@
   // Gpu tracks.
   kGpuFrequency,
 
-  // Linux device tracks.
-  kLinuxDevice,
+  // Linux tracks.
+  kLinuxRuntimePowerManagement,
   kLinuxDeviceFrequency,
 
   // Cpu tracks.
@@ -110,8 +110,8 @@
       return "process";
     case TrackClassification::kChromeProcessInstant:
       return "chrome_process_instant";
-    case TrackClassification::kLinuxDevice:
-      return "linux_device";
+    case TrackClassification::kLinuxRuntimePowerManagement:
+      return "linux_rpm";
     case TrackClassification::kLinuxDeviceFrequency:
       return "linux_device_frequency";
     case TrackClassification::kAsync:
diff --git a/src/trace_processor/importers/common/track_tracker.cc b/src/trace_processor/importers/common/track_tracker.cc
index c7aab1b..963ca83 100644
--- a/src/trace_processor/importers/common/track_tracker.cc
+++ b/src/trace_processor/importers/common/track_tracker.cc
@@ -685,25 +685,6 @@
   return track_id;
 }
 
-TrackId TrackTracker::LegacyInternLinuxDeviceTrack(StringId name) {
-  Dimensions dims_id = SingleDimension(name_id_, Variadic::String(name));
-
-  if (auto* it = tracks_.Find({TrackClassification::kLinuxDevice, dims_id});
-      it) {
-    return *it;
-  }
-
-  tables::LinuxDeviceTrackTable::Row row(name);
-  row.dimension_arg_set_id = dims_id.arg_set_id;
-  row.classification = context_->storage->InternString(
-      TrackClassificationToString(TrackClassification::kLinuxDevice));
-
-  TrackId track_id =
-      context_->storage->mutable_linux_device_track_table()->Insert(row).id;
-  tracks_[{TrackClassification::kLinuxDevice, dims_id}] = track_id;
-  return track_id;
-}
-
 TrackId TrackTracker::LegacyCreateGpuCounterTrack(StringId name,
                                                   uint32_t gpu_id,
                                                   StringId description,
diff --git a/src/trace_processor/importers/common/track_tracker.h b/src/trace_processor/importers/common/track_tracker.h
index 2413054..39aefc4 100644
--- a/src/trace_processor/importers/common/track_tracker.h
+++ b/src/trace_processor/importers/common/track_tracker.h
@@ -21,9 +21,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <functional>
-#include <limits>
 #include <optional>
-#include <vector>
 
 #include "perfetto/ext/base/flat_hash_map.h"
 #include "perfetto/ext/base/hash.h"
@@ -135,6 +133,12 @@
     return DimensionsBuilder(this);
   }
 
+  Dimensions SingleDimension(StringId key, Variadic val) {
+    std::array args{GlobalArgsTracker::CompactArg{key, key, val}};
+    return Dimensions{
+        context_->global_args_tracker->AddArgSet(args.data(), 0, 1)};
+  }
+
   // Interns track into TrackTable. If the track created with below arguments
   // already exists, returns the TrackTable::Id of the track.
   TrackId InternTrack(TrackClassification,
@@ -238,11 +242,6 @@
                                                      int32_t consumer_id,
                                                      int32_t uid);
 
-  // Interns a track associated with a Linux device (where a Linux device
-  // implies a kernel-level device managed by a Linux driver).
-  // TODO(mayzner): Remove when all usages migrated to new track design.
-  TrackId LegacyInternLinuxDeviceTrack(StringId name);
-
   // Creates a counter track associated with a GPU into the storage.
   // TODO(mayzner): Remove when all usages migrated to new track design.
   TrackId LegacyCreateGpuCounterTrack(StringId name,
@@ -310,12 +309,6 @@
   static constexpr size_t kGroupCount =
       static_cast<uint32_t>(Group::kSizeSentinel);
 
-  Dimensions SingleDimension(StringId key, Variadic val) {
-    std::array args{GlobalArgsTracker::CompactArg{key, key, val}};
-    return Dimensions{
-        context_->global_args_tracker->AddArgSet(args.data(), 0, 1)};
-  }
-
   TrackId CreateTrack(TrackClassification,
                       std::optional<Dimensions>,
                       StringId name);
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 9594dd0..403a9df 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -15,15 +15,29 @@
  */
 
 #include "src/trace_processor/importers/ftrace/ftrace_parser.h"
-#include <optional>
 
+#include <algorithm>
+#include <array>
+#include <cinttypes>
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <optional>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "perfetto/base/compiler.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/base/status.h"
 #include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/string_view.h"
+#include "perfetto/protozero/field.h"
 #include "perfetto/protozero/proto_decoder.h"
-
+#include "perfetto/protozero/proto_utils.h"
+#include "perfetto/public/compiler.h"
 #include "perfetto/trace_processor/basic_types.h"
+#include "perfetto/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/common/async_track_set_tracker.h"
 #include "src/trace_processor/importers/common/cpu_tracker.h"
@@ -32,9 +46,12 @@
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/system_info_tracker.h"
 #include "src/trace_processor/importers/common/thread_state_tracker.h"
+#include "src/trace_processor/importers/common/track_classification.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/importers/ftrace/binder_tracker.h"
+#include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
 #include "src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.h"
+#include "src/trace_processor/importers/ftrace/pkvm_hyp_cpu_tracker.h"
 #include "src/trace_processor/importers/ftrace/v4l2_tracker.h"
 #include "src/trace_processor/importers/ftrace/virtio_video_tracker.h"
 #include "src/trace_processor/importers/i2c/i2c_tracker.h"
@@ -46,6 +63,8 @@
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/types/softirq_action.h"
 #include "src/trace_processor/types/tcp_state.h"
+#include "src/trace_processor/types/variadic.h"
+#include "src/trace_processor/types/version_number.h"
 
 #include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
 #include "protos/perfetto/trace/ftrace/android_fs.pbzero.h"
@@ -322,6 +341,8 @@
       sched_waking_name_id_(context->storage->InternString("sched_waking")),
       cpu_id_(context->storage->InternString("cpu")),
       ucpu_id_(context->storage->InternString("ucpu")),
+      linux_device_name_id_(
+          context->storage->InternString("linux_device_name")),
       suspend_resume_name_id_(
           context->storage->InternString("Suspend/Resume Latency")),
       suspend_resume_minimal_name_id_(
@@ -3605,15 +3626,16 @@
 
   // Device here refers to anything managed by a Linux kernel driver.
   std::string device_name = rpm_event.name().ToStdString();
-  int32_t rpm_status = rpm_event.status();
-  StringId device_name_string_id =
-      context_->storage->InternString(device_name.c_str());
-  TrackId track_id = context_->track_tracker->LegacyInternLinuxDeviceTrack(
+  StringId device_name_string_id = context_->storage->InternString(device_name);
+  TrackId track_id = context_->track_tracker->InternTrack(
+      TrackClassification::kLinuxRuntimePowerManagement,
+      context_->track_tracker->SingleDimension(
+          linux_device_name_id_, Variadic::String(device_name_string_id)),
       device_name_string_id);
 
   // A `runtime_status` event implies a potential change in state. Hence, if an
   // active slice exists for this device, end that slice.
-  if (devices_with_active_rpm_slice_.find(device_name) !=
+  if (devices_with_active_rpm_slice_.find(device_name_string_id) !=
       devices_with_active_rpm_slice_.end()) {
     context_->slice_tracker->End(ts, track_id);
   }
@@ -3621,14 +3643,15 @@
   // To reduce visual clutter, the "SUSPENDED" state will be omitted from the
   // visualization, as devices typically spend the majority of their time in
   // this state.
+  int32_t rpm_status = rpm_event.status();
   if (rpm_status == RPM_SUSPENDED) {
-    devices_with_active_rpm_slice_.erase(device_name);
+    devices_with_active_rpm_slice_.erase(device_name_string_id);
     return;
   }
 
   context_->slice_tracker->Begin(ts, track_id, /*category=*/kNullStringId,
                                  /*raw_name=*/GetRpmStatusStringId(rpm_status));
-  devices_with_active_rpm_slice_.insert(device_name);
+  devices_with_active_rpm_slice_.insert(device_name_string_id);
 }
 
 // Parses `device_pm_callback_start` events and begins corresponding slices in
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index 341fcbe..335649d 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -33,11 +33,12 @@
 #include "src/trace_processor/importers/ftrace/gpu_work_period_tracker.h"
 #include "src/trace_processor/importers/ftrace/iostat_tracker.h"
 #include "src/trace_processor/importers/ftrace/mali_gpu_event_tracker.h"
+#include "src/trace_processor/importers/ftrace/pixel_mm_kswapd_event_tracker.h"
 #include "src/trace_processor/importers/ftrace/pkvm_hyp_cpu_tracker.h"
 #include "src/trace_processor/importers/ftrace/rss_stat_tracker.h"
 #include "src/trace_processor/importers/ftrace/thermal_tracker.h"
 #include "src/trace_processor/importers/ftrace/virtio_gpu_tracker.h"
-#include "src/trace_processor/importers/ftrace/pixel_mm_kswapd_event_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
 namespace perfetto {
@@ -332,6 +333,7 @@
   const StringId sched_waking_name_id_;
   const StringId cpu_id_;
   const StringId ucpu_id_;
+  const StringId linux_device_name_id_;
   const StringId suspend_resume_name_id_;
   const StringId suspend_resume_minimal_name_id_;
   const StringId suspend_resume_minimal_slice_name_id_;
@@ -499,7 +501,7 @@
 
   // Tracks Linux devices with active runtime power management (RPM) status
   // slices.
-  std::unordered_set<std::string> devices_with_active_rpm_slice_;
+  std::unordered_set<StringId> devices_with_active_rpm_slice_;
 
   // Tracks unique identifiers ("cookies") to create separate async tracks for
   // the Suspend/Resume UI track. The separation prevents unnestable slices from
diff --git a/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc b/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc
index 2022952..88d492a 100644
--- a/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc
+++ b/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc
@@ -16,10 +16,15 @@
 
 #include "src/trace_processor/importers/proto/profile_packet_sequence_state.h"
 
+#include <cstddef>
 #include <cstdint>
 #include <memory>
 #include <optional>
+#include <string>
 
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/utils.h"
+#include "perfetto/trace_processor/ref_counted.h"
 #include "src/trace_processor/importers/common/mapping_tracker.h"
 #include "src/trace_processor/importers/common/stack_profile_tracker.h"
 #include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
@@ -131,7 +136,7 @@
   profile_packet_sequence_state().FinalizeProfile();
 
   EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].build_id(),
-              context.storage->InternString({kBuildIDHexName}));
+              context.storage->InternString(kBuildIDHexName));
   EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].exact_offset(),
               kMappingExactOffset);
   EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].start_offset(),
diff --git a/src/trace_processor/storage/trace_storage.h b/src/trace_processor/storage/trace_storage.h
index 2e2a3ec..51d6323 100644
--- a/src/trace_processor/storage/trace_storage.h
+++ b/src/trace_processor/storage/trace_storage.h
@@ -231,6 +231,12 @@
   virtual StringId InternString(base::StringView str) {
     return string_pool_.InternString(str);
   }
+  virtual StringId InternString(const char* str) {
+    return InternString(base::StringView(str));
+  }
+  virtual StringId InternString(const std::string& str) {
+    return InternString(base::StringView(str));
+  }
 
   // Example usage: SetStats(stats::android_log_num_failed, 42);
   void SetStats(size_t key, int64_t value) {
@@ -387,13 +393,6 @@
     return &energy_counter_track_table_;
   }
 
-  const tables::LinuxDeviceTrackTable& linux_device_track_table() const {
-    return linux_device_track_table_;
-  }
-  tables::LinuxDeviceTrackTable* mutable_linux_device_track_table() {
-    return &linux_device_track_table_;
-  }
-
   const tables::UidCounterTrackTable& uid_counter_track_table() const {
     return uid_counter_track_table_;
   }
@@ -1078,8 +1077,6 @@
       &string_pool_, &uid_track_table_};
   tables::ProcessTrackTable process_track_table_{&string_pool_, &track_table_};
   tables::ThreadTrackTable thread_track_table_{&string_pool_, &track_table_};
-  tables::LinuxDeviceTrackTable linux_device_track_table_{&string_pool_,
-                                                          &track_table_};
 
   // Track tables for counter events.
   tables::CounterTrackTable counter_track_table_{&string_pool_, &track_table_};
diff --git a/src/trace_processor/tables/table_destructors.cc b/src/trace_processor/tables/table_destructors.cc
index e49761c..4451dc0 100644
--- a/src/trace_processor/tables/table_destructors.cc
+++ b/src/trace_processor/tables/table_destructors.cc
@@ -123,7 +123,6 @@
 EnergyCounterTrackTable::~EnergyCounterTrackTable() = default;
 UidCounterTrackTable::~UidCounterTrackTable() = default;
 EnergyPerUidCounterTrackTable::~EnergyPerUidCounterTrackTable() = default;
-LinuxDeviceTrackTable::~LinuxDeviceTrackTable() = default;
 
 // trace_proto_tables_py.h
 ExperimentalProtoPathTable::~ExperimentalProtoPathTable() = default;
diff --git a/src/trace_processor/tables/track_tables.py b/src/trace_processor/tables/track_tables.py
index bba3d18..d1d3301 100644
--- a/src/trace_processor/tables/track_tables.py
+++ b/src/trace_processor/tables/track_tables.py
@@ -341,24 +341,6 @@
             'ordinal': 'ordinal of energy consumer'
         }))
 
-LINUX_DEVICE_TRACK_TABLE = Table(
-    python_module=__file__,
-    class_name='LinuxDeviceTrackTable',
-    sql_name='linux_device_track',
-    columns=[],
-    parent=TRACK_TABLE,
-    tabledoc=TableDoc(
-        doc='''
-          Slice data corresponding to runtime power state transitions
-          associated with Linux devices (where a Linux device is anything
-          managed by a Linux driver). The name of each track corresponds to the
-          device name as recognized by the linux kernel running on the system.
-        ''',
-        group='Tracks',
-        # No additional columns are needed because the track name implicitly
-        # serves as the device name, providing all required information.
-        columns={}))
-
 UID_COUNTER_TRACK_TABLE = Table(
     python_module=__file__,
     class_name='UidCounterTrackTable',
@@ -396,7 +378,6 @@
     GPU_TRACK_TABLE,
     GPU_WORK_PERIOD_TRACK_TABLE,
     IRQ_COUNTER_TRACK_TABLE,
-    LINUX_DEVICE_TRACK_TABLE,
     PROCESS_COUNTER_TRACK_TABLE,
     PROCESS_TRACK_TABLE,
     SOFTIRQ_COUNTER_TRACK_TABLE,
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index f9f2d32..765d82f 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -950,7 +950,6 @@
   RegisterStaticTable(storage->mutable_gpu_counter_group_table());
   RegisterStaticTable(storage->mutable_perf_counter_track_table());
   RegisterStaticTable(storage->mutable_energy_counter_track_table());
-  RegisterStaticTable(storage->mutable_linux_device_track_table());
   RegisterStaticTable(storage->mutable_uid_counter_track_table());
   RegisterStaticTable(storage->mutable_energy_per_uid_counter_track_table());
 
diff --git a/ui/src/core/default_plugins.ts b/ui/src/core/default_plugins.ts
index c9549c4..b16083e 100644
--- a/ui/src/core/default_plugins.ts
+++ b/ui/src/core/default_plugins.ts
@@ -39,7 +39,7 @@
   'dev.perfetto.RestorePinnedTrack',
   'dev.perfetto.TimelineSync',
   'dev.perfetto.TraceMetadata',
-  'org.kernel.LinuxKernelDevices',
+  'org.kernel.LinuxKernelSubsystems',
   'org.kernel.SuspendResumeLatency',
   'perfetto.AndroidLog',
   'perfetto.Annotation',
diff --git a/ui/src/core_plugins/async_slices/index.ts b/ui/src/core_plugins/async_slices/index.ts
index 6c16c90..c8f8e6e 100644
--- a/ui/src/core_plugins/async_slices/index.ts
+++ b/ui/src/core_plugins/async_slices/index.ts
@@ -110,6 +110,9 @@
         where
           t.type in ('__intrinsic_track', 'gpu_track', '__intrinsic_cpu_track')
           and (name != '${suspendResumeLatencyTrackName}' or name is null)
+          and classification not in (
+            'linux_rpm'
+          )
         group by parent_id, name
       ),
       intermediate_groups as (
diff --git a/ui/src/plugins/org.kernel.LinuxKernelDevices/OWNERS b/ui/src/plugins/org.kernel.LinuxKernelSubsystems/OWNERS
similarity index 100%
rename from ui/src/plugins/org.kernel.LinuxKernelDevices/OWNERS
rename to ui/src/plugins/org.kernel.LinuxKernelSubsystems/OWNERS
diff --git a/ui/src/plugins/org.kernel.LinuxKernelDevices/index.ts b/ui/src/plugins/org.kernel.LinuxKernelSubsystems/index.ts
similarity index 62%
rename from ui/src/plugins/org.kernel.LinuxKernelDevices/index.ts
rename to ui/src/plugins/org.kernel.LinuxKernelSubsystems/index.ts
index 0c000a5..4941206 100644
--- a/ui/src/plugins/org.kernel.LinuxKernelDevices/index.ts
+++ b/ui/src/plugins/org.kernel.LinuxKernelSubsystems/index.ts
@@ -19,29 +19,46 @@
 import {SLICE_TRACK_KIND} from '../../public/track_kinds';
 import {TrackNode} from '../../public/workspace';
 
-// This plugin renders visualizations of runtime power state transitions for
-// Linux kernel devices (devices managed by Linux drivers).
-class LinuxKernelDevices implements PerfettoPlugin {
+// This plugin renders visualizations of subsystems of the Linux kernel.
+class LinuxKernelSubsystems implements PerfettoPlugin {
   async onTraceLoad(ctx: Trace): Promise<void> {
+    const kernel = new TrackNode({
+      title: 'Linux Kernel',
+      isSummary: true,
+    });
+    const rpm = await this.addRpmTracks(ctx);
+    if (rpm.hasChildren) {
+      ctx.workspace.addChildInOrder(kernel);
+      kernel.addChildInOrder(rpm);
+    }
+  }
+
+  // Add tracks to visualize the runtime power state transitions for Linux
+  // kernel devices (devices managed by Linux drivers).
+  async addRpmTracks(ctx: Trace) {
     const result = await ctx.engine.query(`
       select
         t.id as trackId,
-        t.name
-      from linux_device_track t
+        extract_arg(t.dimension_arg_set_id, 'linux_device_name') as deviceName
+      from track t
       join _slice_track_summary using (id)
-      order by t.name;
+      where classification = 'linux_rpm'
+      order by deviceName;
     `);
 
     const it = result.iter({
-      name: STR_NULL,
+      deviceName: STR_NULL,
       trackId: NUM,
     });
-
+    const rpm = new TrackNode({
+      title: 'Runtime Power Management',
+      isSummary: true,
+    });
     for (; it.valid(); it.next()) {
       const trackId = it.trackId;
-      const title = it.name ?? `${trackId}`;
+      const title = it.deviceName ?? `${trackId}`;
 
-      const uri = `/kernel_devices/${title}`;
+      const uri = `/linux/rpm/${title}`;
       ctx.tracks.registerTrack({
         uri,
         title,
@@ -59,18 +76,14 @@
           groupName: `Linux Kernel Devices`,
         },
       });
-      const group = new TrackNode({
-        title: 'Linux Kernel Devices',
-        isSummary: true,
-      });
       const track = new TrackNode({uri, title});
-      group.addChildInOrder(track);
-      ctx.workspace.addChildInOrder(group);
+      rpm.addChildInOrder(track);
     }
+    return rpm;
   }
 }
 
 export const plugin: PluginDescriptor = {
-  pluginId: 'org.kernel.LinuxKernelDevices',
-  plugin: LinuxKernelDevices,
+  pluginId: 'org.kernel.LinuxKernelSubsystems',
+  plugin: LinuxKernelSubsystems,
 };