• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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