1// Copyright (C) 2021 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 { 16 ACTUAL_FRAMES_SLICE_TRACK_KIND, 17 EXPECTED_FRAMES_SLICE_TRACK_KIND, 18} from '../../public'; 19import {Plugin, PluginContextTrace, PluginDescriptor} from '../../public'; 20import {getTrackName} from '../../public/utils'; 21import {NUM, NUM_NULL, STR, STR_NULL} from '../../trace_processor/query_result'; 22 23import {ActualFramesTrack} from './actual_frames_track'; 24import {ExpectedFramesTrack} from './expected_frames_track'; 25 26class FramesPlugin implements Plugin { 27 async onTraceLoad(ctx: PluginContextTrace): Promise<void> { 28 this.addExpectedFrames(ctx); 29 this.addActualFrames(ctx); 30 } 31 32 async addExpectedFrames(ctx: PluginContextTrace): Promise<void> { 33 const {engine} = ctx; 34 const result = await engine.query(` 35 select 36 upid, 37 t.name as trackName, 38 t.track_ids as trackIds, 39 process.name as processName, 40 process.pid as pid, 41 __max_layout_depth(t.track_count, t.track_ids) as maxDepth 42 from _process_track_summary_by_upid_and_name t 43 join process using(upid) 44 where t.name = "Expected Timeline" 45 `); 46 47 const it = result.iter({ 48 upid: NUM, 49 trackName: STR_NULL, 50 trackIds: STR, 51 processName: STR_NULL, 52 pid: NUM_NULL, 53 maxDepth: NUM, 54 }); 55 56 for (; it.valid(); it.next()) { 57 const upid = it.upid; 58 const trackName = it.trackName; 59 const rawTrackIds = it.trackIds; 60 const trackIds = rawTrackIds.split(',').map((v) => Number(v)); 61 const processName = it.processName; 62 const pid = it.pid; 63 const maxDepth = it.maxDepth; 64 65 const displayName = getTrackName({ 66 name: trackName, 67 upid, 68 pid, 69 processName, 70 kind: 'ExpectedFrames', 71 }); 72 73 ctx.registerTrack({ 74 uri: `perfetto.ExpectedFrames#${upid}`, 75 displayName, 76 trackIds, 77 kind: EXPECTED_FRAMES_SLICE_TRACK_KIND, 78 trackFactory: ({trackKey}) => { 79 return new ExpectedFramesTrack(engine, maxDepth, trackKey, trackIds); 80 }, 81 }); 82 } 83 } 84 85 async addActualFrames(ctx: PluginContextTrace): Promise<void> { 86 const {engine} = ctx; 87 const result = await engine.query(` 88 select 89 upid, 90 t.name as trackName, 91 t.track_ids as trackIds, 92 process.name as processName, 93 process.pid as pid, 94 __max_layout_depth(t.track_count, t.track_ids) as maxDepth 95 from _process_track_summary_by_upid_and_name t 96 join process using(upid) 97 where t.name = "Actual Timeline" 98 `); 99 100 const it = result.iter({ 101 upid: NUM, 102 trackName: STR_NULL, 103 trackIds: STR, 104 processName: STR_NULL, 105 pid: NUM_NULL, 106 maxDepth: NUM_NULL, 107 }); 108 for (; it.valid(); it.next()) { 109 const upid = it.upid; 110 const trackName = it.trackName; 111 const rawTrackIds = it.trackIds; 112 const trackIds = rawTrackIds.split(',').map((v) => Number(v)); 113 const processName = it.processName; 114 const pid = it.pid; 115 const maxDepth = it.maxDepth; 116 117 if (maxDepth === null) { 118 // If there are no slices in this track, skip it. 119 continue; 120 } 121 122 const kind = 'ActualFrames'; 123 const displayName = getTrackName({ 124 name: trackName, 125 upid, 126 pid, 127 processName, 128 kind, 129 }); 130 131 ctx.registerTrack({ 132 uri: `perfetto.ActualFrames#${upid}`, 133 displayName, 134 trackIds, 135 kind: ACTUAL_FRAMES_SLICE_TRACK_KIND, 136 trackFactory: ({trackKey}) => { 137 return new ActualFramesTrack(engine, maxDepth, trackKey, trackIds); 138 }, 139 }); 140 } 141 } 142} 143 144export const plugin: PluginDescriptor = { 145 pluginId: 'perfetto.Frames', 146 plugin: FramesPlugin, 147}; 148