1fb726d48Sopenharmony_ci 2fb726d48Sopenharmony_ci/* 3fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 4fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 5fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License. 6fb726d48Sopenharmony_ci * You may obtain a copy of the License at 7fb726d48Sopenharmony_ci * 8fb726d48Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 9fb726d48Sopenharmony_ci * 10fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 11fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 12fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and 14fb726d48Sopenharmony_ci * limitations under the License. 15fb726d48Sopenharmony_ci */ 16fb726d48Sopenharmony_ciimport { type SpSystemTrace } from '../SpSystemTrace'; 17fb726d48Sopenharmony_ciimport { TraceRow } from '../trace/base/TraceRow'; 18fb726d48Sopenharmony_ciimport { renders } from '../../database/ui-worker/ProcedureWorker'; 19fb726d48Sopenharmony_ciimport { type EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; 20fb726d48Sopenharmony_ciimport { type FreqExtendRender, CpuFreqExtendStruct } from '../../database/ui-worker/ProcedureWorkerFreqExtend'; 21fb726d48Sopenharmony_ciimport { type BinderRender, BinderStruct } from '../../database/ui-worker/procedureWorkerBinder'; 22fb726d48Sopenharmony_ciimport { type BaseStruct } from '../../bean/BaseStruct'; 23fb726d48Sopenharmony_ciimport { type AllStatesRender, AllstatesStruct } from '../../database/ui-worker/ProcedureWorkerAllStates'; 24fb726d48Sopenharmony_ciimport { StateGroup } from '../../bean/StateModle'; 25fb726d48Sopenharmony_ciimport { queryAllFuncNames } from '../../database/sql/Func.sql'; 26fb726d48Sopenharmony_ciimport { Utils } from '../trace/base/Utils'; 27fb726d48Sopenharmony_ciimport { TabPaneFreqUsage } from '../trace/sheet/frequsage/TabPaneFreqUsage'; 28fb726d48Sopenharmony_ciconst UNIT_HEIGHT: number = 20; 29fb726d48Sopenharmony_ciconst MS_TO_US: number = 1000000; 30fb726d48Sopenharmony_ciconst MIN_HEIGHT: number = 2; 31fb726d48Sopenharmony_ciexport class SpSegmentationChart { 32fb726d48Sopenharmony_ci static trace: SpSystemTrace; 33fb726d48Sopenharmony_ci static cpuRow: TraceRow<CpuFreqExtendStruct> | undefined; 34fb726d48Sopenharmony_ci static GpuRow: TraceRow<CpuFreqExtendStruct> | undefined; 35fb726d48Sopenharmony_ci static binderRow: TraceRow<BinderStruct> | undefined; 36fb726d48Sopenharmony_ci static schedRow: TraceRow<CpuFreqExtendStruct> | undefined; 37fb726d48Sopenharmony_ci static freqInfoMapData = new Map<number, unknown>(); 38fb726d48Sopenharmony_ci static hoverLine: Array<HeightLine> = []; 39fb726d48Sopenharmony_ci static tabHoverObj: { key: string, cycle: number }; 40fb726d48Sopenharmony_ci private rowFolder!: TraceRow<BaseStruct>; 41fb726d48Sopenharmony_ci static chartData: Array<Object> = []; 42fb726d48Sopenharmony_ci static statesRow: TraceRow<AllstatesStruct> | undefined; 43fb726d48Sopenharmony_ci // 数据切割联动 44fb726d48Sopenharmony_ci static setChartData(type: string, data: Array<FreqChartDataStruct>): void { 45fb726d48Sopenharmony_ci SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 }; 46fb726d48Sopenharmony_ci SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined; 47fb726d48Sopenharmony_ci if (type === 'CPU-FREQ') { 48fb726d48Sopenharmony_ci setCpuData(data); 49fb726d48Sopenharmony_ci } else if (type === 'GPU-FREQ') { 50fb726d48Sopenharmony_ci setGpuData(data); 51fb726d48Sopenharmony_ci } else { 52fb726d48Sopenharmony_ci setSchedData(data); 53fb726d48Sopenharmony_ci } 54fb726d48Sopenharmony_ci SpSegmentationChart.trace.refreshCanvas(false); 55fb726d48Sopenharmony_ci } 56fb726d48Sopenharmony_ci 57fb726d48Sopenharmony_ci // state泳道联动 58fb726d48Sopenharmony_ci static setStateChartData(data: Array<StateGroup>) { 59fb726d48Sopenharmony_ci SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 }; 60fb726d48Sopenharmony_ci SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined; 61fb726d48Sopenharmony_ci let stateChartData = new Array(); 62fb726d48Sopenharmony_ci stateChartData = data.map(v => { 63fb726d48Sopenharmony_ci return { 64fb726d48Sopenharmony_ci dur: v.dur, 65fb726d48Sopenharmony_ci chartDur: v.chartDur, 66fb726d48Sopenharmony_ci pid: v.pid, 67fb726d48Sopenharmony_ci tid: v.tid, 68fb726d48Sopenharmony_ci end_ts: v.startTs! + v.chartDur!, 69fb726d48Sopenharmony_ci id: v.id, 70fb726d48Sopenharmony_ci name: 'all-state', 71fb726d48Sopenharmony_ci startTime: v.startTs, 72fb726d48Sopenharmony_ci start_ts: v.startTs, 73fb726d48Sopenharmony_ci state: v.state, 74fb726d48Sopenharmony_ci type: v.type, 75fb726d48Sopenharmony_ci cycle: v.cycle, 76fb726d48Sopenharmony_ci }; 77fb726d48Sopenharmony_ci }); 78fb726d48Sopenharmony_ci SpSegmentationChart.statesRow!.dataList = []; 79fb726d48Sopenharmony_ci SpSegmentationChart.statesRow!.dataListCache = []; 80fb726d48Sopenharmony_ci SpSegmentationChart.statesRow!.isComplete = false; 81fb726d48Sopenharmony_ci // @ts-ignore 82fb726d48Sopenharmony_ci SpSegmentationChart.statesRow!.supplier = (): Promise<Array<ThreadStruct>> => 83fb726d48Sopenharmony_ci new Promise<Array<AllstatesStruct>>((resolve) => resolve(stateChartData)); 84fb726d48Sopenharmony_ci SpSegmentationChart.trace.refreshCanvas(false); 85fb726d48Sopenharmony_ci }; 86fb726d48Sopenharmony_ci 87fb726d48Sopenharmony_ci // binder联动调用 88fb726d48Sopenharmony_ci static setBinderChartData(data: Array<Array<FreqChartDataStruct>>): void { 89fb726d48Sopenharmony_ci SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 }; 90fb726d48Sopenharmony_ci SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined; 91fb726d48Sopenharmony_ci BinderStruct.maxHeight = 0; 92fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.dataList = []; 93fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.dataListCache = []; 94fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.isComplete = false; 95fb726d48Sopenharmony_ci if (data.length === 0) { 96fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.style.height = `40px`; 97fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.funcMaxHeight = 40; 98fb726d48Sopenharmony_ci // @ts-ignore 99fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.supplier = (): Promise<Array<FreqChartDataStruct>> => 100fb726d48Sopenharmony_ci new Promise<Array<FreqChartDataStruct>>((resolve) => resolve([])); 101fb726d48Sopenharmony_ci } else { 102fb726d48Sopenharmony_ci let binderList: Array<FreqChartDataStruct> = []; 103fb726d48Sopenharmony_ci let chartData: Array<FreqChartDataStruct> = []; 104fb726d48Sopenharmony_ci setBinderData(data, binderList); 105fb726d48Sopenharmony_ci chartData = binderList.map((v: FreqChartDataStruct) => { 106fb726d48Sopenharmony_ci return { 107fb726d48Sopenharmony_ci cpu: 108fb726d48Sopenharmony_ci v.name === 'binder transaction' 109fb726d48Sopenharmony_ci ? 0 110fb726d48Sopenharmony_ci : v.name === 'binder transaction async' 111fb726d48Sopenharmony_ci ? 1 112fb726d48Sopenharmony_ci : v.name === 'binder reply' 113fb726d48Sopenharmony_ci ? MS_TO_US 114fb726d48Sopenharmony_ci : 3, 115fb726d48Sopenharmony_ci startNS: v.startNS, 116fb726d48Sopenharmony_ci dur: v.dur, 117fb726d48Sopenharmony_ci name: `${v.name}`, 118fb726d48Sopenharmony_ci value: v.value, 119fb726d48Sopenharmony_ci depth: v.depth, 120fb726d48Sopenharmony_ci cycle: v.cycle, 121fb726d48Sopenharmony_ci }; 122fb726d48Sopenharmony_ci }); 123fb726d48Sopenharmony_ci // @ts-ignore 124fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.supplier = (): Promise<Array<FreqChartDataStruct>> => 125fb726d48Sopenharmony_ci new Promise<Array<FreqChartDataStruct>>((resolve) => resolve(chartData)); 126fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.style.height = `${BinderStruct.maxHeight > MIN_HEIGHT ? BinderStruct.maxHeight * UNIT_HEIGHT + UNIT_HEIGHT : 40}px`; 127fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.funcMaxHeight = BinderStruct.maxHeight > MIN_HEIGHT ? BinderStruct.maxHeight * UNIT_HEIGHT + UNIT_HEIGHT : 40; 128fb726d48Sopenharmony_ci } 129fb726d48Sopenharmony_ci TraceRow.range!.refresh = true; 130fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.needRefresh = true; 131fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.draw(false); 132fb726d48Sopenharmony_ci if (SpSegmentationChart.binderRow!.collect) { 133fb726d48Sopenharmony_ci window.publish(window.SmartEvent.UI.RowHeightChange, { 134fb726d48Sopenharmony_ci expand: SpSegmentationChart.binderRow!.funcExpand, 135fb726d48Sopenharmony_ci value: SpSegmentationChart.binderRow!.funcMaxHeight - 40, 136fb726d48Sopenharmony_ci }); 137fb726d48Sopenharmony_ci } 138fb726d48Sopenharmony_ci SpSegmentationChart.trace.favoriteChartListEL?.scrollTo(0, 0); 139fb726d48Sopenharmony_ci SpSegmentationChart.trace.refreshCanvas(false); 140fb726d48Sopenharmony_ci } 141fb726d48Sopenharmony_ci // 悬浮联动 142fb726d48Sopenharmony_ci static tabHover(type: string, tableIsHover: boolean = false, cycle: number = -1): void { 143fb726d48Sopenharmony_ci if (tableIsHover) { 144fb726d48Sopenharmony_ci if (SpSegmentationChart.tabHoverObj.cycle === cycle && SpSegmentationChart.tabHoverObj.key === type) { 145fb726d48Sopenharmony_ci SpSegmentationChart.tabHoverObj = { cycle: -1, key: '' }; 146fb726d48Sopenharmony_ci } else { 147fb726d48Sopenharmony_ci SpSegmentationChart.tabHoverObj = { cycle, key: type }; 148fb726d48Sopenharmony_ci } 149fb726d48Sopenharmony_ci } else { 150fb726d48Sopenharmony_ci SpSegmentationChart.tabHoverObj = { cycle: -1, key: '' }; 151fb726d48Sopenharmony_ci } 152fb726d48Sopenharmony_ci 153fb726d48Sopenharmony_ci SpSegmentationChart.trace.refreshCanvas(false); 154fb726d48Sopenharmony_ci } 155fb726d48Sopenharmony_ci constructor(trace: SpSystemTrace) { 156fb726d48Sopenharmony_ci SpSegmentationChart.trace = trace; 157fb726d48Sopenharmony_ci } 158fb726d48Sopenharmony_ci async init() { 159fb726d48Sopenharmony_ci if (Utils.getInstance().getCallStatckMap().size > 0) { 160fb726d48Sopenharmony_ci await this.initFolder(); 161fb726d48Sopenharmony_ci await this.initCpuFreq(); 162fb726d48Sopenharmony_ci await this.initGpuTrace(); 163fb726d48Sopenharmony_ci await this.initSchedTrace(); 164fb726d48Sopenharmony_ci await this.initBinderTrace(); 165fb726d48Sopenharmony_ci await this.initAllStates(); 166fb726d48Sopenharmony_ci } else { 167fb726d48Sopenharmony_ci return; 168fb726d48Sopenharmony_ci } 169fb726d48Sopenharmony_ci } 170fb726d48Sopenharmony_ci async initFolder() { 171fb726d48Sopenharmony_ci let row = TraceRow.skeleton(); 172fb726d48Sopenharmony_ci row.rowId = 'segmentation'; 173fb726d48Sopenharmony_ci row.index = 0; 174fb726d48Sopenharmony_ci row.rowType = TraceRow.ROW_TYPE_SPSEGNENTATION; 175fb726d48Sopenharmony_ci row.rowParentId = ''; 176fb726d48Sopenharmony_ci row.folder = true; 177fb726d48Sopenharmony_ci row.style.height = '40px'; 178fb726d48Sopenharmony_ci row.name = 'Segmentation'; 179fb726d48Sopenharmony_ci row.supplier = (): Promise<Array<BaseStruct>> => new Promise<Array<BaseStruct>>((resolve) => resolve([])); 180fb726d48Sopenharmony_ci row.onThreadHandler = (useCache): void => { 181fb726d48Sopenharmony_ci row.canvasSave(SpSegmentationChart.trace.canvasPanelCtx!); 182fb726d48Sopenharmony_ci if (row.expansion) { 183fb726d48Sopenharmony_ci SpSegmentationChart.trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); 184fb726d48Sopenharmony_ci } else { 185fb726d48Sopenharmony_ci (renders['empty'] as EmptyRender).renderMainThread( 186fb726d48Sopenharmony_ci { 187fb726d48Sopenharmony_ci context: SpSegmentationChart.trace.canvasPanelCtx, 188fb726d48Sopenharmony_ci useCache: useCache, 189fb726d48Sopenharmony_ci type: '', 190fb726d48Sopenharmony_ci }, 191fb726d48Sopenharmony_ci row 192fb726d48Sopenharmony_ci ); 193fb726d48Sopenharmony_ci } 194fb726d48Sopenharmony_ci row.canvasRestore(SpSegmentationChart.trace.canvasPanelCtx!); 195fb726d48Sopenharmony_ci }; 196fb726d48Sopenharmony_ci this.rowFolder = row; 197fb726d48Sopenharmony_ci SpSegmentationChart.trace.rowsEL?.appendChild(row); 198fb726d48Sopenharmony_ci } 199fb726d48Sopenharmony_ci async initCpuFreq() { 200fb726d48Sopenharmony_ci // json文件泳道 201fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow = TraceRow.skeleton<CpuFreqExtendStruct>(); 202fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.rowId = 'cpu-freq'; 203fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.rowType = TraceRow.ROW_TYPE_CPU_COMPUTILITY; 204fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.rowParentId = ''; 205fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.style.height = '40px'; 206fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.name = 'Cpu Computility'; 207fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.favoriteChangeHandler = SpSegmentationChart.trace.favoriteChangeHandler; 208fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.addRowCheckFilePop(); 209fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.rowSetting = 'checkFile'; 210fb726d48Sopenharmony_ci // 拿到了用户传递的数据 211fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.onRowCheckFileChangeHandler = (): void => { 212fb726d48Sopenharmony_ci SpSegmentationChart.freqInfoMapData = new Map<number, unknown>(); 213fb726d48Sopenharmony_ci if (sessionStorage.getItem('freqInfoData')) { 214fb726d48Sopenharmony_ci // @ts-ignore 215fb726d48Sopenharmony_ci let chartData = JSON.parse(JSON.parse(sessionStorage.getItem('freqInfoData'))); 216fb726d48Sopenharmony_ci let mapData = new Map<number, number>(); 217fb726d48Sopenharmony_ci // @ts-ignore 218fb726d48Sopenharmony_ci chartData.map((v) => { 219fb726d48Sopenharmony_ci for (let key in v.freqInfo) { 220fb726d48Sopenharmony_ci mapData.set(Number(key), Number(v.freqInfo[key])); 221fb726d48Sopenharmony_ci } 222fb726d48Sopenharmony_ci SpSegmentationChart.freqInfoMapData.set(v.cpuId, {'smtRate': v.smtRate, mapData}); 223fb726d48Sopenharmony_ci mapData = new Map(); 224fb726d48Sopenharmony_ci }); 225fb726d48Sopenharmony_ci TabPaneFreqUsage.refresh(); 226fb726d48Sopenharmony_ci } 227fb726d48Sopenharmony_ci }; 228fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.focusHandler = (ev): void => { 229fb726d48Sopenharmony_ci SpSegmentationChart.trace?.displayTip( 230fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow!, 231fb726d48Sopenharmony_ci CpuFreqExtendStruct.hoverStruct, 232fb726d48Sopenharmony_ci `<span>${CpuFreqExtendStruct.hoverStruct === undefined ? 0 : CpuFreqExtendStruct.hoverStruct.value! 233fb726d48Sopenharmony_ci }</span>` 234fb726d48Sopenharmony_ci ); 235fb726d48Sopenharmony_ci }; 236fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.findHoverStruct = (): void => { 237fb726d48Sopenharmony_ci CpuFreqExtendStruct.hoverStruct = SpSegmentationChart.cpuRow!.getHoverStruct(); 238fb726d48Sopenharmony_ci }; 239fb726d48Sopenharmony_ci // @ts-ignore 240fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.supplier = (): Promise<Array<freqChartDataStruct>> => 241fb726d48Sopenharmony_ci new Promise<Array<FreqChartDataStruct>>((resolve) => resolve([])); 242fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow.onThreadHandler = (useCache): void => { 243fb726d48Sopenharmony_ci let context: CanvasRenderingContext2D; 244fb726d48Sopenharmony_ci if (SpSegmentationChart.cpuRow!.currentContext) { 245fb726d48Sopenharmony_ci context = SpSegmentationChart.cpuRow!.currentContext; 246fb726d48Sopenharmony_ci } else { 247fb726d48Sopenharmony_ci context = SpSegmentationChart.cpuRow!.collect 248fb726d48Sopenharmony_ci ? SpSegmentationChart.trace.canvasFavoritePanelCtx! 249fb726d48Sopenharmony_ci : SpSegmentationChart.trace.canvasPanelCtx!; 250fb726d48Sopenharmony_ci } 251fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow!.canvasSave(context); 252fb726d48Sopenharmony_ci (renders['freq-extend'] as FreqExtendRender).renderMainThread( 253fb726d48Sopenharmony_ci { 254fb726d48Sopenharmony_ci context: context, 255fb726d48Sopenharmony_ci useCache: useCache, 256fb726d48Sopenharmony_ci type: 'CPU-FREQ', 257fb726d48Sopenharmony_ci }, 258fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow! 259fb726d48Sopenharmony_ci ); 260fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow!.canvasRestore(context); 261fb726d48Sopenharmony_ci }; 262fb726d48Sopenharmony_ci SpSegmentationChart.trace.rowsEL?.appendChild(SpSegmentationChart.cpuRow); 263fb726d48Sopenharmony_ci this.rowFolder!.addChildTraceRow(SpSegmentationChart.cpuRow); 264fb726d48Sopenharmony_ci } 265fb726d48Sopenharmony_ci async initGpuTrace() { 266fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow = TraceRow.skeleton<CpuFreqExtendStruct>(); 267fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.rowId = 'gpurow'; 268fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.rowType = TraceRow.ROW_TYPE_GPU_COMPUTILITY; 269fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.rowParentId = ''; 270fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.style.height = '40px'; 271fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.name = 'Gpu Computility'; 272fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.favoriteChangeHandler = SpSegmentationChart.trace.favoriteChangeHandler; 273fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.selectChangeHandler = SpSegmentationChart.trace.selectChangeHandler; 274fb726d48Sopenharmony_ci // @ts-ignore 275fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.supplier = (): Promise<Array<freqChartDataStruct>> => 276fb726d48Sopenharmony_ci new Promise<Array<FreqChartDataStruct>>((resolve) => resolve([])); 277fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.focusHandler = (ev): void => { 278fb726d48Sopenharmony_ci SpSegmentationChart.trace?.displayTip( 279fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow!, 280fb726d48Sopenharmony_ci CpuFreqExtendStruct.hoverStruct, 281fb726d48Sopenharmony_ci `<span>${CpuFreqExtendStruct.hoverStruct === undefined ? 0 : CpuFreqExtendStruct.hoverStruct.value! 282fb726d48Sopenharmony_ci }</span>` 283fb726d48Sopenharmony_ci ); 284fb726d48Sopenharmony_ci }; 285fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.findHoverStruct = (): void => { 286fb726d48Sopenharmony_ci CpuFreqExtendStruct.hoverStruct = SpSegmentationChart.GpuRow!.getHoverStruct(); 287fb726d48Sopenharmony_ci }; 288fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow.onThreadHandler = (useCache): void => { 289fb726d48Sopenharmony_ci let context: CanvasRenderingContext2D; 290fb726d48Sopenharmony_ci if (SpSegmentationChart.GpuRow!.currentContext) { 291fb726d48Sopenharmony_ci context = SpSegmentationChart.GpuRow!.currentContext; 292fb726d48Sopenharmony_ci } else { 293fb726d48Sopenharmony_ci context = SpSegmentationChart.GpuRow!.collect 294fb726d48Sopenharmony_ci ? SpSegmentationChart.trace.canvasFavoritePanelCtx! 295fb726d48Sopenharmony_ci : SpSegmentationChart.trace.canvasPanelCtx!; 296fb726d48Sopenharmony_ci } 297fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow!.canvasSave(context); 298fb726d48Sopenharmony_ci (renders['freq-extend'] as FreqExtendRender).renderMainThread( 299fb726d48Sopenharmony_ci { 300fb726d48Sopenharmony_ci context: context, 301fb726d48Sopenharmony_ci useCache: useCache, 302fb726d48Sopenharmony_ci type: 'GPU-FREQ', 303fb726d48Sopenharmony_ci }, 304fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow! 305fb726d48Sopenharmony_ci ); 306fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow!.canvasRestore(context); 307fb726d48Sopenharmony_ci }; 308fb726d48Sopenharmony_ci SpSegmentationChart.trace.rowsEL?.appendChild(SpSegmentationChart.GpuRow); 309fb726d48Sopenharmony_ci this.rowFolder!.addChildTraceRow(SpSegmentationChart.GpuRow); 310fb726d48Sopenharmony_ci } 311fb726d48Sopenharmony_ci async initSchedTrace() { 312fb726d48Sopenharmony_ci SpSegmentationChart.schedRow = TraceRow.skeleton<CpuFreqExtendStruct>(); 313fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.rowId = 'sched_switch Count'; 314fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.rowType = TraceRow.ROW_TYPE_SCHED_SWITCH; 315fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.rowParentId = ''; 316fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.style.height = '40px'; 317fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.name = 'Sched_switch Count'; 318fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.favoriteChangeHandler = SpSegmentationChart.trace.favoriteChangeHandler; 319fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.selectChangeHandler = SpSegmentationChart.trace.selectChangeHandler; 320fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.focusHandler = (ev): void => { 321fb726d48Sopenharmony_ci SpSegmentationChart.trace?.displayTip( 322fb726d48Sopenharmony_ci SpSegmentationChart.schedRow!, 323fb726d48Sopenharmony_ci CpuFreqExtendStruct.hoverStruct, 324fb726d48Sopenharmony_ci `<span>${CpuFreqExtendStruct.hoverStruct?.value!}</span>` 325fb726d48Sopenharmony_ci ); 326fb726d48Sopenharmony_ci }; 327fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.findHoverStruct = (): void => { 328fb726d48Sopenharmony_ci CpuFreqExtendStruct.hoverStruct = SpSegmentationChart.schedRow!.getHoverStruct(); 329fb726d48Sopenharmony_ci }; 330fb726d48Sopenharmony_ci // @ts-ignore 331fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.supplier = (): Promise<Array<freqChartDataStruct>> => 332fb726d48Sopenharmony_ci new Promise<Array<FreqChartDataStruct>>((resolve) => resolve([])); 333fb726d48Sopenharmony_ci SpSegmentationChart.schedRow.onThreadHandler = (useCache): void => { 334fb726d48Sopenharmony_ci let context: CanvasRenderingContext2D; 335fb726d48Sopenharmony_ci if (SpSegmentationChart.schedRow!.currentContext) { 336fb726d48Sopenharmony_ci context = SpSegmentationChart.schedRow!.currentContext; 337fb726d48Sopenharmony_ci } else { 338fb726d48Sopenharmony_ci context = SpSegmentationChart.schedRow!.collect 339fb726d48Sopenharmony_ci ? SpSegmentationChart.trace.canvasFavoritePanelCtx! 340fb726d48Sopenharmony_ci : SpSegmentationChart.trace.canvasPanelCtx!; 341fb726d48Sopenharmony_ci } 342fb726d48Sopenharmony_ci SpSegmentationChart.schedRow!.canvasSave(context); 343fb726d48Sopenharmony_ci (renders['freq-extend'] as FreqExtendRender).renderMainThread( 344fb726d48Sopenharmony_ci { 345fb726d48Sopenharmony_ci context: context, 346fb726d48Sopenharmony_ci useCache: useCache, 347fb726d48Sopenharmony_ci type: 'SCHED-SWITCH', 348fb726d48Sopenharmony_ci }, 349fb726d48Sopenharmony_ci SpSegmentationChart.schedRow! 350fb726d48Sopenharmony_ci ); 351fb726d48Sopenharmony_ci SpSegmentationChart.schedRow!.canvasRestore(context); 352fb726d48Sopenharmony_ci }; 353fb726d48Sopenharmony_ci SpSegmentationChart.trace.rowsEL?.appendChild(SpSegmentationChart.schedRow); 354fb726d48Sopenharmony_ci this.rowFolder!.addChildTraceRow(SpSegmentationChart.schedRow); 355fb726d48Sopenharmony_ci } 356fb726d48Sopenharmony_ci 357fb726d48Sopenharmony_ci async initAllStates() { 358fb726d48Sopenharmony_ci SpSegmentationChart.statesRow = TraceRow.skeleton<AllstatesStruct>(); 359fb726d48Sopenharmony_ci SpSegmentationChart.statesRow.rowId = `statesrow`; 360fb726d48Sopenharmony_ci SpSegmentationChart.statesRow.rowType = TraceRow.ROW_TYPE_THREAD; 361fb726d48Sopenharmony_ci SpSegmentationChart.statesRow.rowParentId = ''; 362fb726d48Sopenharmony_ci SpSegmentationChart.statesRow.style.height = '30px'; 363fb726d48Sopenharmony_ci SpSegmentationChart.statesRow.name = `All States`; 364fb726d48Sopenharmony_ci SpSegmentationChart.statesRow.favoriteChangeHandler = SpSegmentationChart.trace.favoriteChangeHandler; 365fb726d48Sopenharmony_ci SpSegmentationChart.statesRow.selectChangeHandler = SpSegmentationChart.trace.selectChangeHandler; 366fb726d48Sopenharmony_ci // @ts-ignore 367fb726d48Sopenharmony_ci SpSegmentationChart.statesRow.supplier = (): Promise<Array<freqChartDataStruct>> => 368fb726d48Sopenharmony_ci new Promise<Array<FreqChartDataStruct>>((resolve) => resolve([])); 369fb726d48Sopenharmony_ci SpSegmentationChart.statesRow.onThreadHandler = (useCache) => { 370fb726d48Sopenharmony_ci let context: CanvasRenderingContext2D; 371fb726d48Sopenharmony_ci if (SpSegmentationChart.statesRow!.currentContext) { 372fb726d48Sopenharmony_ci context = SpSegmentationChart.statesRow!.currentContext; 373fb726d48Sopenharmony_ci } else { 374fb726d48Sopenharmony_ci context = SpSegmentationChart.statesRow!.collect ? SpSegmentationChart.trace.canvasFavoritePanelCtx! : SpSegmentationChart.trace.canvasPanelCtx!; 375fb726d48Sopenharmony_ci } 376fb726d48Sopenharmony_ci SpSegmentationChart.statesRow!.canvasSave(context); 377fb726d48Sopenharmony_ci (renders.stateCut as AllStatesRender).renderMainThread( 378fb726d48Sopenharmony_ci { 379fb726d48Sopenharmony_ci context: context, 380fb726d48Sopenharmony_ci useCache: useCache, 381fb726d48Sopenharmony_ci type: ``, 382fb726d48Sopenharmony_ci translateY: SpSegmentationChart.statesRow!.translateY, 383fb726d48Sopenharmony_ci }, 384fb726d48Sopenharmony_ci SpSegmentationChart.statesRow! 385fb726d48Sopenharmony_ci ); 386fb726d48Sopenharmony_ci SpSegmentationChart.statesRow!.canvasRestore(context); 387fb726d48Sopenharmony_ci }; 388fb726d48Sopenharmony_ci SpSegmentationChart.trace.rowsEL?.appendChild(SpSegmentationChart.statesRow); 389fb726d48Sopenharmony_ci this.rowFolder!.addChildTraceRow(SpSegmentationChart.statesRow); 390fb726d48Sopenharmony_ci } 391fb726d48Sopenharmony_ci 392fb726d48Sopenharmony_ci async initBinderTrace() { 393fb726d48Sopenharmony_ci SpSegmentationChart.binderRow = TraceRow.skeleton<BinderStruct>(); 394fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.rowId = 'binderrow'; 395fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.rowType = TraceRow.ROW_TYPE_BINDER_COUNT; 396fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.enableCollapseChart(40, SpSegmentationChart.trace); 397fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.rowParentId = ''; 398fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.name = 'Binder Count'; 399fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.style.height = '40px'; 400fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.favoriteChangeHandler = SpSegmentationChart.trace.favoriteChangeHandler; 401fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.selectChangeHandler = SpSegmentationChart.trace.selectChangeHandler; 402fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.findHoverStruct = () => { 403fb726d48Sopenharmony_ci BinderStruct.hoverCpuFreqStruct = SpSegmentationChart.binderRow!.dataListCache.find((v: BinderStruct) => { 404fb726d48Sopenharmony_ci if (SpSegmentationChart.binderRow!.isHover) { 405fb726d48Sopenharmony_ci if (v.frame!.x < SpSegmentationChart.binderRow!.hoverX + 1 && 406fb726d48Sopenharmony_ci v.frame!.x + v.frame!.width > SpSegmentationChart.binderRow!.hoverX - 1 && 407fb726d48Sopenharmony_ci (BinderStruct.maxHeight * 20 - v.depth * 20 + 20) < SpSegmentationChart.binderRow!.hoverY && 408fb726d48Sopenharmony_ci BinderStruct.maxHeight * 20 - v.depth * 20 + v.value * 20 + 20 > SpSegmentationChart.binderRow!.hoverY) { 409fb726d48Sopenharmony_ci return v; 410fb726d48Sopenharmony_ci } 411fb726d48Sopenharmony_ci } 412fb726d48Sopenharmony_ci }) 413fb726d48Sopenharmony_ci }; 414fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.focusHandler = (ev): void => { 415fb726d48Sopenharmony_ci SpSegmentationChart.trace!.displayTip( 416fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!, 417fb726d48Sopenharmony_ci BinderStruct.hoverCpuFreqStruct, 418fb726d48Sopenharmony_ci `<span style='font-weight: bold;'>Cycle: ${BinderStruct.hoverCpuFreqStruct ? BinderStruct.hoverCpuFreqStruct.cycle : 0 419fb726d48Sopenharmony_ci }</span><br> 420fb726d48Sopenharmony_ci <span style='font-weight: bold;'>Name: ${BinderStruct.hoverCpuFreqStruct ? BinderStruct.hoverCpuFreqStruct.name : '' 421fb726d48Sopenharmony_ci }</span><br> 422fb726d48Sopenharmony_ci <span style='font-weight: bold;'>Count: ${BinderStruct.hoverCpuFreqStruct ? BinderStruct.hoverCpuFreqStruct.value : 0 423fb726d48Sopenharmony_ci }</span>` 424fb726d48Sopenharmony_ci ); 425fb726d48Sopenharmony_ci }; 426fb726d48Sopenharmony_ci 427fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.supplier = (): Promise<Array<BinderStruct>> => 428fb726d48Sopenharmony_ci new Promise<Array<BinderStruct>>((resolve) => resolve([])); 429fb726d48Sopenharmony_ci SpSegmentationChart.binderRow.onThreadHandler = (useCache): void => { 430fb726d48Sopenharmony_ci let context: CanvasRenderingContext2D; 431fb726d48Sopenharmony_ci if (SpSegmentationChart.binderRow!.currentContext) { 432fb726d48Sopenharmony_ci context = SpSegmentationChart.binderRow!.currentContext; 433fb726d48Sopenharmony_ci } else { 434fb726d48Sopenharmony_ci context = SpSegmentationChart.binderRow!.collect 435fb726d48Sopenharmony_ci ? SpSegmentationChart.trace.canvasFavoritePanelCtx! 436fb726d48Sopenharmony_ci : SpSegmentationChart.trace.canvasPanelCtx!; 437fb726d48Sopenharmony_ci } 438fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.canvasSave(context); 439fb726d48Sopenharmony_ci (renders.binder as BinderRender).renderMainThread( 440fb726d48Sopenharmony_ci { 441fb726d48Sopenharmony_ci context: context, 442fb726d48Sopenharmony_ci useCache: useCache, 443fb726d48Sopenharmony_ci type: 'BINDER', 444fb726d48Sopenharmony_ci }, 445fb726d48Sopenharmony_ci SpSegmentationChart.binderRow! 446fb726d48Sopenharmony_ci ); 447fb726d48Sopenharmony_ci SpSegmentationChart.binderRow!.canvasRestore(context); 448fb726d48Sopenharmony_ci }; 449fb726d48Sopenharmony_ci SpSegmentationChart.trace.rowsEL?.appendChild(SpSegmentationChart.binderRow); 450fb726d48Sopenharmony_ci this.rowFolder!.addChildTraceRow(SpSegmentationChart.binderRow); 451fb726d48Sopenharmony_ci } 452fb726d48Sopenharmony_ci} 453fb726d48Sopenharmony_ciclass FreqChartDataStruct { 454fb726d48Sopenharmony_ci colorIndex?: number = 0; 455fb726d48Sopenharmony_ci dur: number = 0; 456fb726d48Sopenharmony_ci value: number = 0; 457fb726d48Sopenharmony_ci startNS: number = 0; 458fb726d48Sopenharmony_ci cycle: number = 0; 459fb726d48Sopenharmony_ci depth?: number = 1; 460fb726d48Sopenharmony_ci name?: string = ''; 461fb726d48Sopenharmony_ci} 462fb726d48Sopenharmony_ci 463fb726d48Sopenharmony_cifunction setCpuData(data: Array<FreqChartDataStruct>) { 464fb726d48Sopenharmony_ci let currentMaxValue = 0; 465fb726d48Sopenharmony_ci data.map((v: FreqChartDataStruct) => { 466fb726d48Sopenharmony_ci if (v.value > currentMaxValue) { 467fb726d48Sopenharmony_ci currentMaxValue = v.value; 468fb726d48Sopenharmony_ci } 469fb726d48Sopenharmony_ci }); 470fb726d48Sopenharmony_ci CpuFreqExtendStruct.hoverType = 'CPU-FREQ'; 471fb726d48Sopenharmony_ci CpuFreqExtendStruct.cpuMaxValue = currentMaxValue; 472fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow!.dataList = []; 473fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow!.dataListCache = []; 474fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow!.isComplete = false; 475fb726d48Sopenharmony_ci // @ts-ignore 476fb726d48Sopenharmony_ci SpSegmentationChart.cpuRow!.supplier = (): Promise<Array<FreqChartDataStruct>> => 477fb726d48Sopenharmony_ci new Promise<Array<FreqChartDataStruct>>((resolve) => resolve(data)); 478fb726d48Sopenharmony_ci} 479fb726d48Sopenharmony_cifunction setGpuData(data: Array<FreqChartDataStruct>): void { 480fb726d48Sopenharmony_ci let currentMaxValue = 0; 481fb726d48Sopenharmony_ci data.map((v: FreqChartDataStruct) => { 482fb726d48Sopenharmony_ci if (v.value && v.value > currentMaxValue!) { 483fb726d48Sopenharmony_ci currentMaxValue = v.value; 484fb726d48Sopenharmony_ci } 485fb726d48Sopenharmony_ci }); 486fb726d48Sopenharmony_ci CpuFreqExtendStruct.hoverType = 'GPU-FREQ'; 487fb726d48Sopenharmony_ci CpuFreqExtendStruct.gpuMaxValue = currentMaxValue; 488fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow!.dataList = []; 489fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow!.dataListCache = []; 490fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow!.isComplete = false; 491fb726d48Sopenharmony_ci // @ts-ignore 492fb726d48Sopenharmony_ci SpSegmentationChart.GpuRow!.supplier = (): Promise<Array<FreqChartDataStruct>> => 493fb726d48Sopenharmony_ci new Promise<Array<FreqChartDataStruct>>((resolve) => resolve(data)); 494fb726d48Sopenharmony_ci} 495fb726d48Sopenharmony_cifunction setSchedData(data: Array<FreqChartDataStruct>): void { 496fb726d48Sopenharmony_ci let currentMaxValue = 0; 497fb726d48Sopenharmony_ci data.map((v: FreqChartDataStruct) => { 498fb726d48Sopenharmony_ci if (v.value && v.value > currentMaxValue!) { 499fb726d48Sopenharmony_ci currentMaxValue = v.value; 500fb726d48Sopenharmony_ci } 501fb726d48Sopenharmony_ci }); 502fb726d48Sopenharmony_ci CpuFreqExtendStruct.hoverType = 'SCHED-SWITCH'; 503fb726d48Sopenharmony_ci CpuFreqExtendStruct.schedMaxValue = currentMaxValue!; 504fb726d48Sopenharmony_ci SpSegmentationChart.schedRow!.dataList = []; 505fb726d48Sopenharmony_ci SpSegmentationChart.schedRow!.dataListCache = []; 506fb726d48Sopenharmony_ci SpSegmentationChart.schedRow!.isComplete = false; 507fb726d48Sopenharmony_ci // @ts-ignore 508fb726d48Sopenharmony_ci SpSegmentationChart.schedRow!.supplier = (): Promise<Array<FreqChartDataStruct>> => 509fb726d48Sopenharmony_ci new Promise<Array<FreqChartDataStruct>>((resolve) => resolve(data)); 510fb726d48Sopenharmony_ci} 511fb726d48Sopenharmony_cifunction setBinderData(data: Array<Array<FreqChartDataStruct>>, binderList: Array<FreqChartDataStruct>): void { 512fb726d48Sopenharmony_ci data.map((v: Array<FreqChartDataStruct>) => { 513fb726d48Sopenharmony_ci // 统计每一竖列的最大count 514fb726d48Sopenharmony_ci let listCount = 0; 515fb726d48Sopenharmony_ci v.map((t: FreqChartDataStruct) => { 516fb726d48Sopenharmony_ci listCount += t.value; 517fb726d48Sopenharmony_ci if (t.name === 'binder transaction') { 518fb726d48Sopenharmony_ci t.depth = t.value; 519fb726d48Sopenharmony_ci } 520fb726d48Sopenharmony_ci if (t.name === 'binder transaction async') { 521fb726d48Sopenharmony_ci t.depth = 522fb726d48Sopenharmony_ci t.value + 523fb726d48Sopenharmony_ci (v.filter((i: FreqChartDataStruct) => { 524fb726d48Sopenharmony_ci return i.name === 'binder transaction'; 525fb726d48Sopenharmony_ci }).length > 0 526fb726d48Sopenharmony_ci ? v.filter((i: FreqChartDataStruct) => { 527fb726d48Sopenharmony_ci return i.name === 'binder transaction'; 528fb726d48Sopenharmony_ci })[0].value 529fb726d48Sopenharmony_ci : 0); 530fb726d48Sopenharmony_ci } 531fb726d48Sopenharmony_ci if (t.name === 'binder reply') { 532fb726d48Sopenharmony_ci t.depth = 533fb726d48Sopenharmony_ci t.value + 534fb726d48Sopenharmony_ci (v.filter((i: FreqChartDataStruct) => { 535fb726d48Sopenharmony_ci return i.name === 'binder transaction'; 536fb726d48Sopenharmony_ci }).length > 0 537fb726d48Sopenharmony_ci ? v.filter((i: FreqChartDataStruct) => { 538fb726d48Sopenharmony_ci return i.name === 'binder transaction'; 539fb726d48Sopenharmony_ci })[0].value 540fb726d48Sopenharmony_ci : 0) + 541fb726d48Sopenharmony_ci (v.filter((i: FreqChartDataStruct) => { 542fb726d48Sopenharmony_ci return i.name === 'binder transaction async'; 543fb726d48Sopenharmony_ci }).length > 0 544fb726d48Sopenharmony_ci ? v.filter((i: FreqChartDataStruct) => { 545fb726d48Sopenharmony_ci return i.name === 'binder transaction async'; 546fb726d48Sopenharmony_ci })[0].value 547fb726d48Sopenharmony_ci : 0); 548fb726d48Sopenharmony_ci } 549fb726d48Sopenharmony_ci if (t.name === 'binder async rcv') { 550fb726d48Sopenharmony_ci t.depth = 551fb726d48Sopenharmony_ci t.value + 552fb726d48Sopenharmony_ci (v.filter((i: FreqChartDataStruct) => { 553fb726d48Sopenharmony_ci return i.name === 'binder transaction'; 554fb726d48Sopenharmony_ci }).length > 0 555fb726d48Sopenharmony_ci ? v.filter((i: FreqChartDataStruct) => { 556fb726d48Sopenharmony_ci return i.name === 'binder transaction'; 557fb726d48Sopenharmony_ci })[0].value 558fb726d48Sopenharmony_ci : 0) + 559fb726d48Sopenharmony_ci (v.filter((i: FreqChartDataStruct) => { 560fb726d48Sopenharmony_ci return i.name === 'binder transaction async'; 561fb726d48Sopenharmony_ci }).length > 0 562fb726d48Sopenharmony_ci ? v.filter((i: FreqChartDataStruct) => { 563fb726d48Sopenharmony_ci return i.name === 'binder transaction async'; 564fb726d48Sopenharmony_ci })[0].value 565fb726d48Sopenharmony_ci : 0) + 566fb726d48Sopenharmony_ci (v.filter((i: FreqChartDataStruct) => { 567fb726d48Sopenharmony_ci return i.name === 'binder reply'; 568fb726d48Sopenharmony_ci }).length > 0 569fb726d48Sopenharmony_ci ? v.filter((i: FreqChartDataStruct) => { 570fb726d48Sopenharmony_ci return i.name === 'binder reply'; 571fb726d48Sopenharmony_ci })[0].value 572fb726d48Sopenharmony_ci : 0); 573fb726d48Sopenharmony_ci } 574fb726d48Sopenharmony_ci binderList.push(t); 575fb726d48Sopenharmony_ci }); 576fb726d48Sopenharmony_ci BinderStruct.maxHeight = 577fb726d48Sopenharmony_ci BinderStruct.maxHeight > listCount ? BinderStruct.maxHeight : JSON.parse(JSON.stringify(listCount)); 578fb726d48Sopenharmony_ci listCount = 0; 579fb726d48Sopenharmony_ci }); 580fb726d48Sopenharmony_ci} 581fb726d48Sopenharmony_ci 582fb726d48Sopenharmony_ciclass HeightLine { 583fb726d48Sopenharmony_ci key: string = ''; 584fb726d48Sopenharmony_ci cycle: number = -1; 585fb726d48Sopenharmony_ci} 586