1// Copyright (C) 2024 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {NUM, STR_NULL} from '../../trace_processor/query_result'; 16import {Trace} from '../../public/trace'; 17import {PerfettoPlugin} from '../../public/plugin'; 18import {createTraceProcessorSliceTrack} from '../dev.perfetto.TraceProcessorTrack/trace_processor_slice_track'; 19import {SLICE_TRACK_KIND} from '../../public/track_kinds'; 20import {TrackNode} from '../../public/workspace'; 21import TraceProcessorTrackPlugin from '../dev.perfetto.TraceProcessorTrack'; 22 23// This plugin renders visualizations of subsystems of the Linux kernel. 24export default class implements PerfettoPlugin { 25 static readonly id = 'org.kernel.LinuxKernelSubsystems'; 26 static readonly dependencies = [TraceProcessorTrackPlugin]; 27 28 async onTraceLoad(ctx: Trace): Promise<void> { 29 const kernel = new TrackNode({ 30 title: 'Linux Kernel', 31 isSummary: true, 32 }); 33 const rpm = await this.addRpmTracks(ctx); 34 if (rpm.hasChildren) { 35 ctx.workspace.addChildInOrder(kernel); 36 kernel.addChildInOrder(rpm); 37 } 38 } 39 40 // Add tracks to visualize the runtime power state transitions for Linux 41 // kernel devices (devices managed by Linux drivers). 42 async addRpmTracks(ctx: Trace) { 43 const result = await ctx.engine.query(` 44 select 45 t.id as trackId, 46 extract_arg(t.dimension_arg_set_id, 'linux_device') as deviceName 47 from track t 48 join _slice_track_summary using (id) 49 where type = 'linux_rpm' 50 order by deviceName; 51 `); 52 53 const it = result.iter({ 54 deviceName: STR_NULL, 55 trackId: NUM, 56 }); 57 const rpm = new TrackNode({ 58 title: 'Runtime Power Management', 59 isSummary: true, 60 }); 61 for (; it.valid(); it.next()) { 62 const trackId = it.trackId; 63 const title = it.deviceName ?? `${trackId}`; 64 65 const uri = `/linux/rpm/${title}`; 66 ctx.tracks.registerTrack({ 67 uri, 68 title, 69 track: createTraceProcessorSliceTrack({ 70 trace: ctx, 71 uri, 72 trackIds: [trackId], 73 }), 74 tags: { 75 kind: SLICE_TRACK_KIND, 76 trackIds: [trackId], 77 groupName: `Linux Kernel Devices`, 78 }, 79 }); 80 const track = new TrackNode({uri, title}); 81 rpm.addChildInOrder(track); 82 } 83 return rpm; 84 } 85} 86