| // Copyright (C) 2021 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| import {TrackNode} from '../../public/workspace'; |
| import {CPU_FREQ_TRACK_KIND} from '../../public/track_kinds'; |
| import {Trace} from '../../public/trace'; |
| import {PerfettoPlugin} from '../../public/plugin'; |
| import {NUM, NUM_NULL} from '../../trace_processor/query_result'; |
| import {CpuFreqTrack} from './cpu_freq_track'; |
| |
| export default class implements PerfettoPlugin { |
| static readonly id = 'dev.perfetto.CpuFreq'; |
| async onTraceLoad(ctx: Trace): Promise<void> { |
| const {engine} = ctx; |
| |
| const cpus = []; |
| const cpusResult = await engine.query( |
| 'select distinct cpu from cpu_counter_track order by cpu;', |
| ); |
| for (const it = cpusResult.iter({cpu: NUM}); it.valid(); it.next()) { |
| cpus.push(it.cpu); |
| } |
| |
| const maxCpuFreqResult = await engine.query(` |
| select ifnull(max(value), 0) as freq |
| from counter c |
| join cpu_counter_track t on c.track_id = t.id |
| join _counter_track_summary s on t.id = s.id |
| where name = 'cpufreq'; |
| `); |
| const maxCpuFreq = maxCpuFreqResult.firstRow({freq: NUM}).freq; |
| |
| for (const cpu of cpus) { |
| // Only add a cpu freq track if we have cpu freq data. |
| const cpuFreqIdleResult = await engine.query(` |
| select |
| id as cpuFreqId, |
| ( |
| select id |
| from cpu_counter_track |
| where name = 'cpuidle' |
| and cpu = ${cpu} |
| limit 1 |
| ) as cpuIdleId |
| from cpu_counter_track |
| join _counter_track_summary using (id) |
| where name = 'cpufreq' and cpu = ${cpu} |
| limit 1; |
| `); |
| |
| if (cpuFreqIdleResult.numRows() > 0) { |
| const row = cpuFreqIdleResult.firstRow({ |
| cpuFreqId: NUM, |
| cpuIdleId: NUM_NULL, |
| }); |
| const freqTrackId = row.cpuFreqId; |
| const idleTrackId = row.cpuIdleId === null ? undefined : row.cpuIdleId; |
| |
| const config = { |
| cpu, |
| maximumValue: maxCpuFreq, |
| freqTrackId, |
| idleTrackId, |
| }; |
| |
| const uri = `/cpu_freq_cpu${cpu}`; |
| const title = `Cpu ${cpu} Frequency`; |
| ctx.tracks.registerTrack({ |
| uri, |
| title, |
| tags: { |
| kind: CPU_FREQ_TRACK_KIND, |
| cpu, |
| }, |
| track: new CpuFreqTrack(config, ctx), |
| }); |
| const trackNode = new TrackNode({uri, title, sortOrder: -40}); |
| ctx.workspace.addChildInOrder(trackNode); |
| } |
| } |
| } |
| } |