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 {AsyncSliceTrack} from '../dev.perfetto.AsyncSlices/async_slice_track'; 19import {SLICE_TRACK_KIND} from '../../public/track_kinds'; 20import {TrackNode} from '../../public/workspace'; 21import AsyncSlicesPlugin from '../dev.perfetto.AsyncSlices'; 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 = [AsyncSlicesPlugin]; 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 classification = '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: new AsyncSliceTrack(ctx, uri, 0, [trackId]), 70 tags: { 71 kind: SLICE_TRACK_KIND, 72 trackIds: [trackId], 73 groupName: `Linux Kernel Devices`, 74 }, 75 }); 76 const track = new TrackNode({uri, title}); 77 rpm.addChildInOrder(track); 78 } 79 return rpm; 80 } 81} 82