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