xref: /aosp_15_r20/development/tools/winscope/src/viewers/viewer_jank_cujs/presenter.ts (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import {assertDefined} from 'common/assert_utils';
18import {Store} from 'common/store';
19import {Timestamp} from 'common/time';
20import {TimeDuration} from 'common/time_duration';
21import {Trace} from 'trace/trace';
22import {PropertyTreeNode} from 'trace/tree_node/property_tree_node';
23import {
24  AbstractLogViewerPresenter,
25  NotifyLogViewCallbackType,
26} from 'viewers/common/abstract_log_viewer_presenter';
27import {LogPresenter} from 'viewers/common/log_presenter';
28import {PropertiesPresenter} from 'viewers/common/properties_presenter';
29import {TextFilter} from 'viewers/common/text_filter';
30import {LogField, LogHeader} from 'viewers/common/ui_data_log';
31import {CujEntry, CujStatus, UiData} from './ui_data';
32
33export class Presenter extends AbstractLogViewerPresenter<
34  UiData,
35  PropertyTreeNode
36> {
37  private static readonly COLUMNS = {
38    type: {
39      name: 'Type',
40      cssClass: 'jank-cuj-type',
41    },
42    startTime: {
43      name: 'Start Time',
44      cssClass: 'start-time time',
45    },
46    endTime: {
47      name: 'End Time',
48      cssClass: 'end-time time',
49    },
50    duration: {
51      name: 'Duration',
52      cssClass: 'duration right-align',
53    },
54    status: {
55      name: 'Status',
56      cssClass: 'status right-align',
57    },
58  };
59  private transitionTrace: Trace<PropertyTreeNode>;
60
61  protected override logPresenter = new LogPresenter<CujEntry>();
62  protected override propertiesPresenter = new PropertiesPresenter(
63    {},
64    new TextFilter(),
65    [],
66    [],
67  );
68
69  constructor(
70    trace: Trace<PropertyTreeNode>,
71    private readonly storage: Store,
72    notifyViewCallback: NotifyLogViewCallbackType<UiData>,
73  ) {
74    super(trace, notifyViewCallback, UiData.createEmpty());
75    this.transitionTrace = trace;
76  }
77
78  protected override makeHeaders(): LogHeader[] {
79    return [
80      new LogHeader(Presenter.COLUMNS.type),
81      new LogHeader(Presenter.COLUMNS.startTime),
82      new LogHeader(Presenter.COLUMNS.endTime),
83      new LogHeader(Presenter.COLUMNS.duration),
84      new LogHeader(Presenter.COLUMNS.status),
85    ];
86  }
87
88  protected override async makeUiDataEntries(): Promise<CujEntry[]> {
89    const cujs: CujEntry[] = [];
90    for (
91      let traceIndex = 0;
92      traceIndex < this.transitionTrace.lengthEntries;
93      ++traceIndex
94    ) {
95      const entry = assertDefined(this.trace.getEntry(traceIndex));
96      const cujNode = await entry.getValue();
97
98      let status: CujStatus;
99      let statusIcon: string;
100      let statusIconColor: string;
101      if (assertDefined(cujNode.getChildByName('canceled')).getValue()) {
102        status = CujStatus.CANCELLED;
103        statusIcon = 'close';
104        statusIconColor = 'red';
105      } else {
106        status = CujStatus.EXECUTED;
107        statusIcon = 'check';
108        statusIconColor = 'green';
109      }
110
111      const startTs: Timestamp | undefined = cujNode
112        .getChildByName('startTimestamp')
113        ?.getValue();
114      const endTs: Timestamp | undefined = cujNode
115        .getChildByName('endTimestamp')
116        ?.getValue();
117
118      let timeDiff: TimeDuration | undefined = undefined;
119      if (startTs && endTs) {
120        const timeDiffNs = endTs.minus(startTs.getValueNs()).getValueNs();
121        timeDiff = new TimeDuration(timeDiffNs);
122      }
123
124      const cujType = assertDefined(
125        cujNode.getChildByName('cujType'),
126      ).formattedValue();
127
128      const fields: LogField[] = [
129        {spec: Presenter.COLUMNS.type, value: cujType},
130        {
131          spec: Presenter.COLUMNS.startTime,
132          value: startTs ?? Presenter.VALUE_NA,
133        },
134        {
135          spec: Presenter.COLUMNS.endTime,
136          value: endTs ?? Presenter.VALUE_NA,
137        },
138        {
139          spec: Presenter.COLUMNS.duration,
140          value: timeDiff?.format() ?? Presenter.VALUE_NA,
141        },
142        {
143          spec: Presenter.COLUMNS.status,
144          value: status,
145          icon: statusIcon,
146          iconColor: statusIconColor,
147        },
148      ];
149      cujs.push(new CujEntry(entry, fields, cujNode));
150    }
151
152    return cujs;
153  }
154}
155