• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 m from 'mithril';
16
17import {Actions} from '../common/actions';
18import {globals} from './globals';
19import {Button} from '../widgets/button';
20import {Icons} from '../base/semantic_icons';
21import {ThreadSliceTrack} from './thread_slice_track';
22import {uuidv4Sql} from '../base/uuid';
23import {Engine} from '../trace_processor/engine';
24import {createView} from '../trace_processor/sql_utils';
25
26export interface VisualizedArgsTrackAttrs {
27  readonly trackKey: string;
28  readonly engine: Engine;
29  readonly trackId: number;
30  readonly maxDepth: number;
31  readonly argName: string;
32}
33
34export class VisualisedArgsTrack extends ThreadSliceTrack {
35  private readonly viewName: string;
36  private readonly argName: string;
37
38  constructor({
39    trackKey,
40    engine,
41    trackId,
42    maxDepth,
43    argName,
44  }: VisualizedArgsTrackAttrs) {
45    const uuid = uuidv4Sql();
46    const escapedArgName = argName.replace(/[^a-zA-Z]/g, '_');
47    const viewName = `__arg_visualisation_helper_${escapedArgName}_${uuid}_slice`;
48
49    super({engine, trackKey}, trackId, maxDepth, viewName);
50    this.viewName = viewName;
51    this.argName = argName;
52  }
53
54  async onInit() {
55    return await createView(
56      this.engine,
57      this.viewName,
58      `
59        with slice_with_arg as (
60          select
61            slice.id,
62            slice.track_id,
63            slice.ts,
64            slice.dur,
65            slice.thread_dur,
66            NULL as cat,
67            args.display_value as name
68          from slice
69          join args using (arg_set_id)
70          where args.key='${this.argName}'
71        )
72        select
73          *,
74          (select count()
75          from ancestor_slice(s1.id) s2
76          join slice_with_arg s3 on s2.id=s3.id
77          ) as depth
78        from slice_with_arg s1
79        order by id
80      `,
81    );
82  }
83
84  getTrackShellButtons(): m.Children {
85    return m(Button, {
86      onclick: () => {
87        // This behavior differs to the original behavior a little.
88        // Originally, hitting the close button on a single track removed ALL
89        // tracks with this argName, whereas this one only closes the single
90        // track.
91        // This will be easily fixable once we transition to using dynamic
92        // tracks instead of this "initial state" approach to add these tracks.
93        globals.dispatch(Actions.removeTracks({trackKeys: [this.trackKey]}));
94      },
95      icon: Icons.Close,
96      title: 'Close',
97      compact: true,
98    });
99  }
100}
101