• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
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 */
15
16import { BaseElement, element } from '../../base-ui/BaseElement';
17import './trace/TimerShaftElement';
18import './trace/base/TraceRow';
19import { threadPool } from '../database/SqlLite';
20import { TraceRow } from './trace/base/TraceRow';
21import { TimerShaftElement } from './trace/TimerShaftElement';
22import './trace/base/TraceSheet';
23import { TraceSheet } from './trace/base/TraceSheet';
24import { RangeSelect } from './trace/base/RangeSelect';
25import { SelectionParam } from '../bean/BoxSelection';
26import { procedurePool } from '../database/Procedure';
27import { SpApplication } from '../SpApplication';
28import { Flag } from './trace/timer-shaft/Flag';
29import { SlicesTime, SportRuler } from './trace/timer-shaft/SportRuler';
30import { SpHiPerf } from './chart/SpHiPerf';
31import { SearchSdkBean } from '../bean/SearchFuncBean';
32import { info } from '../../log/Log';
33import {
34  drawFlagLineSegment,
35  drawLines,
36  drawLinkLines,
37  drawLogsLineSegment,
38  drawWakeUp,
39  drawWakeUpList,
40  LineType,
41  ns2x,
42  ns2xByTimeShaft,
43  PairPoint,
44  Rect,
45} from '../database/ui-worker/ProcedureWorkerCommon';
46import { SpChartManager } from './chart/SpChartManager';
47import { CpuStruct, WakeupBean } from '../database/ui-worker/cpu/ProcedureWorkerCPU';
48import { ProcessStruct } from '../database/ui-worker/ProcedureWorkerProcess';
49import { CpuFreqStruct } from '../database/ui-worker/ProcedureWorkerFreq';
50import { CpuFreqLimitsStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits';
51import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread';
52import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc';
53import { CpuStateStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuState';
54import { HiPerfCpuStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfCPU2';
55import { HiPerfProcessStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfProcess2';
56import { HiPerfThreadStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfThread2';
57import { HiPerfEventStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfEvent';
58import { HiPerfReportStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfReport';
59import { FpsStruct } from '../database/ui-worker/ProcedureWorkerFPS';
60import { CpuAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerCpuAbility';
61import { DiskAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerDiskIoAbility';
62import { MemoryAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerMemoryAbility';
63import { NetworkAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerNetworkAbility';
64import { ClockStruct } from '../database/ui-worker/ProcedureWorkerClock';
65import { Utils } from './trace/base/Utils';
66import { IrqStruct } from '../database/ui-worker/ProcedureWorkerIrq';
67import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank';
68import { TabPaneCurrent } from './trace/sheet/TabPaneCurrent';
69import { HeapStruct } from '../database/ui-worker/ProcedureWorkerHeap';
70import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil';
71import { HeapSnapshotStruct } from '../database/ui-worker/ProcedureWorkerHeapSnapshot';
72import { HeapDataInterface } from '../../js-heap/HeapDataInterface';
73import { LitTabs } from '../../base-ui/tabs/lit-tabs';
74import { TraceRowConfig } from './trace/base/TraceRowConfig';
75import { TabPaneCurrentSelection } from './trace/sheet/TabPaneCurrentSelection';
76import { SpChartList } from './trace/SpChartList';
77import './trace/SpChartList';
78import { AppStartupStruct } from '../database/ui-worker/ProcedureWorkerAppStartup';
79import { AllAppStartupStruct } from '../database/ui-worker/ProcedureWorkerAllAppStartup';
80import { SoStruct } from '../database/ui-worker/ProcedureWorkerSoInit';
81import { FrameDynamicStruct } from '../database/ui-worker/ProcedureWorkerFrameDynamic';
82import { FrameAnimationStruct } from '../database/ui-worker/ProcedureWorkerFrameAnimation';
83import { FrameSpacingStruct } from '../database/ui-worker/ProcedureWorkerFrameSpacing';
84import { JsCpuProfilerStruct } from '../database/ui-worker/ProcedureWorkerCpuProfiler';
85import { FileInfo } from '../../js-heap/model/UiStruct';
86import { SnapshotStruct } from '../database/ui-worker/ProcedureWorkerSnapshot';
87import { LogStruct } from '../database/ui-worker/ProcedureWorkerLog';
88import { TabPaneFrequencySample } from './trace/sheet/cpu/TabPaneFrequencySample';
89import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample';
90import { TabPaneFlag } from './trace/timer-shaft/TabPaneFlag';
91import { LitTabpane } from '../../base-ui/tabs/lit-tabpane';
92import { HiPerfCallChartStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfCallChart';
93import { InitAnalysis } from '../database/logic-worker/ProcedureLogicWorkerCommon';
94import { searchCpuDataSender } from '../database/data-trafic/CpuDataSender';
95import { resetVSync } from './chart/VSync';
96import { QueryEnum } from '../database/data-trafic/utils/QueryEnum';
97import { SpSystemTraceHtml } from './SpSystemTrace.html';
98import { querySceneSearchFunc, querySearchFunc } from '../database/sql/Func.sql';
99import { queryCpuKeyPathData } from '../database/sql/Cpu.sql';
100import { LtpoStruct } from '../database/ui-worker/ProcedureWorkerLTPO';
101import { HitchTimeStruct } from '../database/ui-worker/ProcedureWorkerHitchTime';
102import {
103  spSystemTraceInit,
104  spSystemTraceInitElement,
105  spSystemTraceInitPointToEvent,
106  spSystemTraceShowStruct,
107} from './SpSystemTrace.init';
108import {
109  spSystemTraceDrawJankLine,
110  spSystemTraceDrawTaskPollLine,
111  spSystemTraceDrawThreadLine,
112} from './SpSystemTrace.line';
113import spSystemTraceOnClickHandler, {
114  spSystemTraceDocumentOnClick,
115  spSystemTraceDocumentOnKeyDown,
116  SpSystemTraceDocumentOnKeyPress,
117  spSystemTraceDocumentOnKeyUp,
118  spSystemTraceDocumentOnMouseDown,
119  spSystemTraceDocumentOnMouseMove,
120  spSystemTraceDocumentOnMouseOut,
121  spSystemTraceDocumentOnMouseUp,
122} from './SpSystemTrace.event';
123
124function dpr(): number {
125  return window.devicePixelRatio || 1;
126}
127
128export class CurrentSlicesTime {
129  startTime: number | undefined;
130  endTime: number | undefined;
131}
132
133type HTMLDivElementAlias = HTMLDivElement | undefined | null;
134type FlagAlias = Flag | undefined | null;
135type SlicesTimeAlias = SlicesTime | undefined | null;
136
137@element('sp-system-trace')
138export class SpSystemTrace extends BaseElement {
139  mouseCurrentPosition = 0;
140  offsetMouse = 0;
141  isMouseLeftDown = false;
142  static scrollViewWidth = 0;
143  static isCanvasOffScreen = true;
144  static DATA_DICT: Map<number, string> = new Map<number, string>();
145  static DATA_TASK_POOL_CALLSTACK: Map<number, { id: number; ts: number; dur: number; name: string }> = new Map<
146    number,
147    { id: number; ts: number; dur: number; name: string }
148  >();
149  static SDK_CONFIG_MAP: any;
150  static sliceRangeMark: any;
151  static wakeupList: Array<WakeupBean> = [];
152  static keyPathList: Array<CpuStruct> = [];
153  static jsProfilerMap: Map<number, any> = new Map<number, any>();
154  times: Set<number> = new Set<number>();
155  currentSlicesTime: CurrentSlicesTime = new CurrentSlicesTime();
156  intersectionObserver: IntersectionObserver | undefined;
157  tipEL: HTMLDivElementAlias;
158  rowsEL: HTMLDivElementAlias;
159  rowsPaneEL: HTMLDivElementAlias;
160  stateRowsId: Array<object> = [];
161  spacerEL: HTMLDivElementAlias;
162  visibleRows: Array<TraceRow<any>> = [];
163  invisibleRows: Array<TraceRow<any>> = [];
164  collectRows: Array<TraceRow<any>> = [];
165  currentRow: TraceRow<any> | undefined | null;
166  keyboardEnable = true;
167  mouseEventEnable = true;
168  currentRowType = ''; /*保存当前鼠标所在行的类型*/
169  observerScrollHeightEnable: boolean = false;
170  observerScrollHeightCallback: Function | undefined;
171  favoriteChartListEL: SpChartList | undefined | null;
172  // @ts-ignore
173  observer = new ResizeObserver((entries) => {
174    if (this.observerScrollHeightEnable && this.observerScrollHeightCallback) {
175      this.observerScrollHeightCallback();
176    }
177  });
178  static btnTimer: any = null;
179  isMousePointInSheet = false;
180  hoverFlag: FlagAlias;
181  selectFlag: FlagAlias;
182  slicestime: SlicesTimeAlias;
183  public timerShaftEL: TimerShaftElement | null | undefined;
184  public traceSheetEL: TraceSheet | undefined | null;
185  public rangeSelect!: RangeSelect;
186  chartManager: SpChartManager | undefined | null;
187  loadTraceCompleted: boolean = false;
188  rangeTraceRow: Array<TraceRow<any>> | undefined = [];
189  canvasFavoritePanelCtx: CanvasRenderingContext2D | null | undefined;
190  canvasPanel: HTMLCanvasElement | null | undefined; //绘制取消收藏后泳道图
191  canvasPanelCtx: CanvasRenderingContext2D | undefined | null;
192  linkNodes: PairPoint[][] = [];
193  public currentClickRow: HTMLDivElement | undefined | null;
194  private litTabs: LitTabs | undefined | null;
195  eventMap: any = {};
196  isSelectClick: boolean = false;
197  selectionParam: SelectionParam | undefined;
198  snapshotFiles: FileInfo | null | undefined;
199  tabCpuFreq: TabPaneFrequencySample | undefined | null;
200  tabCpuState: TabPaneCounterSample | undefined | null;
201  collapseAll: boolean = false;
202  currentCollectGroup: string = '1';
203  private _list: Array<SlicesTime> = [];
204  expandRowList: Array<TraceRow<any>> = [];
205  _slicesList: Array<SlicesTime> = [];
206  _flagList: Array<any> = [];
207
208  set snapshotFile(data: FileInfo) {
209    this.snapshotFiles = data;
210  }
211
212  set slicesList(list: Array<SlicesTime>) {
213    this._slicesList = list;
214  }
215
216  set flagList(list: Array<any>) {
217    this._flagList = list;
218  }
219
220  //节流处理
221  throttle(fn: Function, t: number, ev?: any): Function {
222    let timerId: any = null;
223    return () => {
224      if (!timerId) {
225        timerId = setTimeout(function () {
226          if (ev) {
227            fn(ev);
228          } else {
229            fn();
230          }
231          timerId = null;
232        }, t);
233        this.times.add(timerId);
234      }
235    };
236  }
237
238  // 防抖处理
239  debounce(fn: Function, ms: number, ev?: any): Function {
240    let timerId: undefined | number;
241    return () => {
242      if (timerId) {
243        window.clearTimeout(timerId);
244      } else {
245        timerId = window.setTimeout(() => {
246          if (ev) {
247            fn(ev);
248          } else {
249            fn();
250          }
251          timerId = undefined;
252        }, ms);
253        this.times.add(timerId);
254      }
255    };
256  }
257
258  addPointPair(startPoint: PairPoint, endPoint: PairPoint): void {
259    if (startPoint.rowEL.collect) {
260      startPoint.rowEL.translateY = startPoint.rowEL.getBoundingClientRect().top - 195;
261    } else {
262      startPoint.rowEL.translateY = startPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
263    }
264    if (endPoint.rowEL.collect) {
265      endPoint.rowEL.translateY = endPoint.rowEL.getBoundingClientRect().top - 195;
266    } else {
267      endPoint.rowEL.translateY = endPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
268    }
269    startPoint.y = startPoint.rowEL!.translateY! + startPoint.offsetY;
270    endPoint.y = endPoint.rowEL!.translateY! + endPoint.offsetY;
271    startPoint.backrowEL = startPoint.rowEL;
272    endPoint.backrowEL = endPoint.rowEL;
273    this.linkNodes.push([startPoint, endPoint]);
274  }
275
276  clearPointPair(): void {
277    this.linkNodes.length = 0;
278  }
279
280  removeLinkLinesByBusinessType(...businessTypes: string[]): void {
281    this.linkNodes = this.linkNodes.filter((pointPair) => {
282      return businessTypes.indexOf(pointPair[0].business) <= -1;
283    });
284  }
285
286  hiddenLinkLinesByBusinessType(...businessTypes: string[]): void {
287    this.linkNodes.map((value) => {
288      if (businessTypes.indexOf(value[0].business) !== -1) {
289        value[0].hidden = true;
290        value[1].hidden = true;
291      }
292    });
293  }
294
295  showLinkLinesByBusinessType(...businessTypes: string[]): void {
296    this.linkNodes.map((value) => {
297      if (businessTypes.indexOf(value[0].business) !== -1) {
298        value[0].hidden = false;
299        value[1].hidden = false;
300      }
301    });
302  }
303
304  initElements(): void {
305    spSystemTraceInitElement(this);
306  }
307
308  // 清除上一次点击调用栈产生的三角旗子
309  clearTriangle(flagList: Array<Flag>): void {
310    this.timerShaftEL!.sportRuler!.times = [];
311    for (let i = 0; i < flagList.length; i++) {
312      if (flagList[i].type === 'triangle') {
313        flagList.splice(i, 1);
314        i--;
315      }
316    }
317  }
318
319  pushPidToSelection(selection: SelectionParam, id: string): void {
320    let pid = parseInt(id);
321    if (!selection.processIds.includes(pid)) {
322      selection.processIds.push(pid);
323    }
324  }
325
326  getCollectRows(condition: (row: TraceRow<any>) => boolean): Array<TraceRow<any>> {
327    return this.favoriteChartListEL!.getCollectRows(condition);
328  }
329
330  createPointEvent(it: TraceRow<any>) {
331    let event = this.eventMap[`${it.rowType}`];
332    if (event) {
333      return event;
334    } else {
335      if (it.rowType === TraceRow.ROW_TYPE_HEAP) {
336        event = it.name;
337      } else if (it.rowType === TraceRow.ROW_TYPE_HIPERF_CPU) {
338        event = 'HiPerf Cpu';
339        if (it.rowId === 'HiPerf-cpu-merge') {
340          event = 'HiPerf';
341        }
342      } else if (it.rowType === TraceRow.ROW_TYPE_FILE_SYSTEM) {
343        event = this.handleFileSystemType(it, event);
344      } else if (it.rowType === TraceRow.ROW_TYPE_STATE_ENERGY) {
345        event = it.name;
346      } else if (it.rowType === TraceRow.ROW_TYPE_VM_TRACKER) {
347        if (it.rowParentId === '') {
348          event = 'VM Tracker';
349        } else {
350          event = it.name;
351        }
352      } else if (it.rowType === TraceRow.ROW_TYPE_JANK) {
353        if (it.rowId === 'frameTime' || it.rowParentId === 'frameTime') {
354          event = 'FrameTimeLine';
355        } else if (it.hasAttribute('frame_type')) {
356          event = it.getAttribute('frame_type') + '';
357        }
358      } else if (it.rowType === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) {
359        event = 'DeliverInputEvent';
360        if (it.rowParentId === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) {
361          event = 'DeliverInputEvent Func';
362        }
363      } else {
364        event = it.name;
365      }
366      return event;
367    }
368  }
369
370  private handleFileSystemType(it: TraceRow<any>, event: any) {
371    if (it.rowId === 'FileSystemLogicalWrite') {
372      event = 'FileSystem Logical Write';
373    } else if (it.rowId === 'FileSystemLogicalRead') {
374      event = 'FileSystem Logical Read';
375    } else if (it.rowId === 'FileSystemVirtualMemory') {
376      event = 'Page Fault Trace';
377    } else if (it.rowId!.startsWith('FileSystemDiskIOLatency')) {
378      event = 'Disk I/O Latency';
379      if (it.rowId!.startsWith('FileSystemDiskIOLatency-')) {
380        event = 'Bio Process';
381      }
382    }
383    return event;
384  }
385
386  refreshFavoriteCanvas(): void {
387    this.favoriteChartListEL!.refreshFavoriteCanvas();
388  }
389
390  expansionAllParentRow(currentRow: TraceRow<any>): void {
391    let parentRow = this.rowsEL!.querySelector<TraceRow<any>>(
392      `trace-row[row-id='${currentRow.rowParentId}'][folder][scene]`
393    );
394    if (parentRow) {
395      parentRow.expansion = true;
396      if (this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${parentRow.rowParentId}'][folder]`)) {
397        this.expansionAllParentRow(parentRow);
398      }
399    }
400  }
401
402  canvasPanelConfig(): void {
403    this.canvasPanel!.style.left = `${this.timerShaftEL!.canvas!.offsetLeft!}px`;
404    this.canvasPanel!.width = this.canvasPanel!.offsetWidth * dpr();
405    this.canvasPanel!.height = this.canvasPanel!.offsetHeight * dpr();
406    this.canvasPanelCtx!.scale(dpr(), dpr());
407  }
408
409  getScrollWidth(): number {
410    let totalScrollDiv,
411      scrollDiv,
412      overflowDiv = document.createElement('div');
413    overflowDiv.style.cssText = 'position:absolute; top:-2000px;width:200px; height:200px; overflow:hidden;';
414    totalScrollDiv = document.body.appendChild(overflowDiv).clientWidth;
415    overflowDiv.style.overflowY = 'scroll';
416    scrollDiv = overflowDiv.clientWidth;
417    document.body.removeChild(overflowDiv);
418    return totalScrollDiv - scrollDiv;
419  }
420
421  getShowTab(): Array<string> {
422    let tabpane = this.traceSheetEL!.shadowRoot!.querySelectorAll('lit-tabpane') as NodeListOf<LitTabpane>;
423    let showTab: Array<string> = [];
424    for (let pane of tabpane) {
425      if (pane.getAttribute('hidden') === 'false') {
426        showTab.push(pane.getAttribute('id') || '');
427      }
428    }
429    return showTab;
430  }
431
432  timerShaftELFlagClickHandler = (flag: FlagAlias) => {
433    if (flag) {
434      setTimeout(() => {
435        if (TraceRow.rangeSelectObject) {
436          let showTab = this.getShowTab();
437          this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag', ...showTab).setCurrentFlag(flag);
438        } else {
439          this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag').setCurrentFlag(flag);
440        }
441      }, 100);
442    }
443  };
444
445  timerShaftELFlagChange = (hoverFlag: FlagAlias, selectFlag: FlagAlias) => {
446    this.hoverFlag = hoverFlag;
447    this.selectFlag = selectFlag;
448    this.refreshCanvas(true, 'flagChange');
449  };
450
451  timerShaftELRangeClick = (sliceTime: SlicesTimeAlias): void => {
452    if (sliceTime) {
453      setTimeout(() => {
454        if (TraceRow.rangeSelectObject) {
455          let showTab = this.getShowTab();
456          this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current', ...showTab).setCurrentSlicesTime(sliceTime);
457        } else {
458          this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(sliceTime);
459        }
460      }, 0);
461    }
462  };
463
464  timerShaftELRangeChange = (e: any): void => {
465    TraceRow.range = e;
466    if (TraceRow.rangeSelectObject) {
467      TraceRow.rangeSelectObject!.startX = Math.floor(
468        ns2x(
469          TraceRow.rangeSelectObject!.startNS!,
470          TraceRow.range?.startNS!,
471          TraceRow.range?.endNS!,
472          TraceRow.range?.totalNS!,
473          this.timerShaftEL!.sportRuler!.frame
474        )
475      );
476      TraceRow.rangeSelectObject!.endX = Math.floor(
477        ns2x(
478          TraceRow.rangeSelectObject!.endNS!,
479          TraceRow.range?.startNS!,
480          TraceRow.range?.endNS!,
481          TraceRow.range?.totalNS!,
482          this.timerShaftEL!.sportRuler!.frame
483        )
484      );
485    }
486    //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知
487    this.linkNodes.forEach((it) => {
488      it[0].x = ns2xByTimeShaft(it[0].ns, this.timerShaftEL!);
489      it[1].x = ns2xByTimeShaft(it[1].ns, this.timerShaftEL!);
490    });
491    this.invisibleRows.forEach((it) => (it.needRefresh = true));
492    this.visibleRows.forEach((it) => (it.needRefresh = true));
493    this.refreshCanvas(false, 'rangeChange');
494  };
495  tim: number = -1;
496  top: number = 0;
497  handler: any = undefined;
498  rowsElOnScroll = (e: any): void => {
499    this.linkNodes.forEach((itln) => {
500      if (itln[0].rowEL.collect) {
501        itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195;
502      } else {
503        itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
504      }
505      if (itln[1].rowEL.collect) {
506        itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195;
507      } else {
508        itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
509      }
510      itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY;
511      itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY;
512    });
513    this.hoverStructNull();
514    if (this.scrollTimer) {
515      clearTimeout(this.scrollTimer);
516    }
517    this.scrollTimer = setTimeout(() => {
518      TraceRow.range!.refresh = true;
519      requestAnimationFrame(() => this.refreshCanvas(false));
520    }, 200);
521    requestAnimationFrame(() => this.refreshCanvas(false));
522  };
523
524  private scrollTimer: any;
525
526  favoriteRowsElOnScroll = (e: any): void => {
527    this.rowsElOnScroll(e);
528  };
529
530  offset = 147;
531
532  getRowsContentHeight(): number {
533    return [...this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row:not([sleeping])`)]
534      .map((it) => it.clientHeight)
535      .reduce((acr, cur) => acr + cur, 0);
536  }
537
538  // refresh main canvas and favorite canvas
539  refreshCanvas(cache: boolean, from?: string): void {
540    if (this.visibleRows.length === 0) {
541      return;
542    }
543    //clear main canvas
544    this.canvasPanelCtx!.clearRect(0, 0, this.canvasPanel!.offsetWidth, this.canvasPanel!.offsetHeight);
545    this.favoriteChartListEL!.clearRect();
546    //draw lines for main canvas
547    let rowsContentHeight = this.getRowsContentHeight();
548    let canvasHeight =
549      rowsContentHeight > this.canvasPanel!.clientHeight ? this.canvasPanel!.clientHeight : rowsContentHeight;
550    drawLines(this.canvasPanelCtx!, TraceRow.range?.xs || [], canvasHeight, this.timerShaftEL!.lineColor());
551    //draw lines for favorite canvas
552    this.favoriteChartListEL?.drawLines(TraceRow.range?.xs, this.timerShaftEL!.lineColor()); // chart list
553
554    //canvas translate
555    this.canvasPanel!.style.transform = `translateY(${this.rowsPaneEL!.scrollTop}px)`;
556    //draw trace row
557    this.visibleRows.forEach((v, i) => {
558      if (v.collect) {
559        v.translateY = v.getBoundingClientRect().top - 195;
560      } else {
561        v.translateY = v.offsetTop - this.rowsPaneEL!.scrollTop;
562      }
563      v.draw(cache);
564    });
565    this.drawAllLines();
566  }
567
568  drawWakeUpLine(): void {
569    //draw wakeup for main canvas
570    drawWakeUp(
571      this.canvasPanelCtx,
572      CpuStruct.wakeupBean,
573      TraceRow.range!.startNS,
574      TraceRow.range!.endNS,
575      TraceRow.range!.totalNS,
576      {
577        x: 0,
578        y: 0,
579        width: TraceRow.FRAME_WIDTH,
580        height: this.canvasPanel!.clientHeight!,
581      } as Rect
582    );
583    this.favoriteChartListEL?.drawWakeUp();
584    // draw wakeuplist for main canvas
585    for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) {
586      if (i + 1 == SpSystemTrace.wakeupList.length) {
587        return;
588      }
589      drawWakeUpList(
590        this.canvasPanelCtx,
591        SpSystemTrace.wakeupList[i + 1],
592        TraceRow.range!.startNS,
593        TraceRow.range!.endNS,
594        TraceRow.range!.totalNS,
595        {
596          x: 0,
597          y: 0,
598          width: this.timerShaftEL!.canvas!.clientWidth,
599          height: this.canvasPanel!.clientHeight!,
600        } as Rect
601      );
602      this.favoriteChartListEL?.drawWakeUpList(SpSystemTrace.wakeupList[i + 1]);
603    }
604  }
605
606  drawAllLines(): void {
607    // draw flag line segment for canvas
608    drawFlagLineSegment(
609      this.canvasPanelCtx,
610      this.hoverFlag,
611      this.selectFlag,
612      {
613        x: 0,
614        y: 0,
615        width: this.timerShaftEL?.canvas?.clientWidth,
616        height: this.canvasPanel?.clientHeight,
617      },
618      this.timerShaftEL!
619    );
620    this.favoriteChartListEL?.drawFlagLineSegment(this.hoverFlag, this.selectFlag, this.timerShaftEL!);
621    this.drawWakeUpLine();
622    //draw system logs line segment for canvas
623    drawLogsLineSegment(
624      this.canvasPanelCtx,
625      this.traceSheetEL?.systemLogFlag,
626      {
627        x: 0,
628        y: 0,
629        width: this.timerShaftEL?.canvas?.clientWidth,
630        height: this.canvasPanel?.clientHeight,
631      },
632      this.timerShaftEL!
633    );
634    this.favoriteChartListEL?.drawLogsLineSegment(this.traceSheetEL!.systemLogFlag, this.timerShaftEL!);
635
636    // Draw the connection curve
637    if (this.linkNodes && this.linkNodes.length > 0) {
638      drawLinkLines(
639        this.canvasPanelCtx!,
640        this.linkNodes,
641        this.timerShaftEL!,
642        false,
643        this.favoriteChartListEL!.clientHeight
644      );
645      this.favoriteChartListEL?.drawLinkLines(
646        this.linkNodes,
647        this.timerShaftEL!,
648        true,
649        this.favoriteChartListEL!.clientHeight
650      );
651    }
652  }
653
654  drawAllLine(row: TraceRow<any>) {
655    let context: CanvasRenderingContext2D;
656    if (row.currentContext) {
657      context = row.currentContext;
658    } else {
659      context = row.collect ? this.canvasFavoritePanelCtx! : this.canvasPanelCtx!;
660    }
661    let startNS = TraceRow.range!.startNS;
662    let endNS = TraceRow.range!.endNS;
663    let totalNS = TraceRow.range!.totalNS;
664    drawFlagLineSegment(context, this.hoverFlag, this.selectFlag, row.frame, this.timerShaftEL!);
665    drawWakeUp(context, CpuStruct.wakeupBean, startNS, endNS, totalNS, row.frame);
666    for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) {
667      if (i + 1 == SpSystemTrace.wakeupList.length) {
668        return;
669      }
670      drawWakeUpList(context, SpSystemTrace.wakeupList[i + 1], startNS, endNS, totalNS, row.frame);
671    }
672    drawLogsLineSegment(context, this.traceSheetEL?.systemLogFlag, row.frame, this.timerShaftEL!);
673  }
674
675  documentOnMouseDown = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseDown(this, ev);
676
677  onContextMenuHandler = (e: Event): void => {
678    setTimeout(() => {
679      for (let key of this.keyPressMap.keys()) {
680        if (this.keyPressMap.get(key)) {
681          this.timerShaftEL?.stopWASD({ key: key });
682          this.keyPressMap.set(key, false);
683        }
684      }
685    }, 100);
686  };
687
688  documentOnMouseUp = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseUp(this, ev);
689
690  cancelDrag(): void {
691    this.rangeSelect.drag = false;
692    this.rangeSelect.isMouseDown = false;
693    TraceRow.rangeSelectObject = {
694      startX: 0,
695      endX: 0,
696      startNS: 0,
697      endNS: 0,
698    };
699  }
700
701  documentOnMouseOut = (ev: MouseEvent) => spSystemTraceDocumentOnMouseOut(this, ev);
702
703  keyPressMap: Map<string, boolean> = new Map([
704    ['w', false],
705    ['s', false],
706    ['a', false],
707    ['d', false],
708    ['f', false],
709  ]);
710
711  documentOnKeyDown = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyDown(this, ev);
712
713  documentOnKeyPress = (ev: KeyboardEvent): void => SpSystemTraceDocumentOnKeyPress(this, ev);
714
715  verticalScrollToRow(): void {
716    if (this.currentRow) {
717      //@ts-ignore
718      this.currentRow.scrollIntoViewIfNeeded();
719    }
720  }
721
722  setCurrentSlicesTime(): void {
723    if (CpuStruct.selectCpuStruct) {
724      if (CpuStruct.selectCpuStruct.startTime && CpuStruct.selectCpuStruct.dur) {
725        this.currentSlicesTime.startTime = CpuStruct.selectCpuStruct.startTime;
726        this.currentSlicesTime.endTime = CpuStruct.selectCpuStruct.startTime + CpuStruct.selectCpuStruct.dur;
727      }
728    } else if (ThreadStruct.selectThreadStruct) {
729      if (ThreadStruct.selectThreadStruct.startTime && ThreadStruct.selectThreadStruct.dur) {
730        this.currentSlicesTime.startTime = ThreadStruct.selectThreadStruct.startTime;
731        this.currentSlicesTime.endTime =
732          ThreadStruct.selectThreadStruct.startTime + ThreadStruct.selectThreadStruct.dur;
733      }
734    } else if (FuncStruct.selectFuncStruct) {
735      if (FuncStruct.selectFuncStruct.startTs && FuncStruct.selectFuncStruct.dur) {
736        this.currentSlicesTime.startTime = FuncStruct.selectFuncStruct.startTs;
737        this.currentSlicesTime.endTime = FuncStruct.selectFuncStruct.startTs + FuncStruct.selectFuncStruct.dur;
738      }
739    } else if (IrqStruct.selectIrqStruct) {
740      if (IrqStruct.selectIrqStruct.startNS && IrqStruct.selectIrqStruct.dur) {
741        this.currentSlicesTime.startTime = IrqStruct.selectIrqStruct.startNS;
742        this.currentSlicesTime.endTime = IrqStruct.selectIrqStruct.startNS + IrqStruct.selectIrqStruct.dur;
743      }
744    } else if (TraceRow.rangeSelectObject) {
745      this.currentRow = undefined;
746      if (TraceRow.rangeSelectObject.startNS && TraceRow.rangeSelectObject.endNS) {
747        this.currentSlicesTime.startTime = TraceRow.rangeSelectObject.startNS;
748        this.currentSlicesTime.endTime = TraceRow.rangeSelectObject.endNS;
749      }
750    } else if (JankStruct.selectJankStruct) {
751      if (JankStruct.selectJankStruct.ts && JankStruct.selectJankStruct.dur) {
752        this.currentSlicesTime.startTime = JankStruct.selectJankStruct.ts;
753        this.currentSlicesTime.endTime = JankStruct.selectJankStruct.ts + JankStruct.selectJankStruct.dur;
754      }
755    } else {
756      this.currentSlicesTime.startTime = 0;
757      this.currentSlicesTime.endTime = 0;
758    }
759  }
760
761  public setSLiceMark = (shiftKey: boolean): SlicesTime | null | undefined => {
762    const selectedStruct: any =
763      CpuStruct.selectCpuStruct ||
764      ThreadStruct.selectThreadStruct ||
765      FuncStruct.selectFuncStruct ||
766      IrqStruct.selectIrqStruct ||
767      TraceRow.rangeSelectObject ||
768      JankStruct.selectJankStruct ||
769      AppStartupStruct.selectStartupStruct ||
770      SoStruct.selectSoStruct ||
771      AllAppStartupStruct.selectStartupStruct ||
772      FrameAnimationStruct.selectFrameAnimationStruct ||
773      JsCpuProfilerStruct.selectJsCpuProfilerStruct;
774    this.calculateSlicesTime(selectedStruct, shiftKey);
775
776    return this.slicestime;
777  };
778
779  private calculateSlicesTime(selectedStruct: any, shiftKey: boolean): void {
780    if (selectedStruct) {
781      const startTs = selectedStruct.startTs || selectedStruct.startTime || selectedStruct.startNS || 0;
782      const dur = selectedStruct.dur || selectedStruct.totalTime || selectedStruct.endNS || 0;
783      this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, startTs + dur, shiftKey);
784    } else {
785      this.slicestime = this.timerShaftEL?.setSlicesMark();
786    }
787  }
788
789  stopWASD = (): void => {
790    setTimeout((): void => {
791      for (let key of this.keyPressMap.keys()) {
792        if (this.keyPressMap.get(key)) {
793          this.timerShaftEL?.stopWASD({ key: key });
794          this.keyPressMap.set(key, false);
795        }
796      }
797    }, 100);
798  };
799
800  // 一直按着回车键的时候执行搜索功能
801  continueSearch = (ev: KeyboardEvent) => {
802    if (ev.key === 'Enter') {
803      if (ev.shiftKey) {
804        this.dispatchEvent(
805          new CustomEvent('trace-previous-data', {
806            detail: { down: true },
807            composed: false,
808          })
809        );
810      } else {
811        this.dispatchEvent(
812          new CustomEvent('trace-next-data', {
813            detail: { down: true },
814            composed: false,
815          })
816        );
817      }
818    }
819  };
820
821  documentOnKeyUp = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyUp(this, ev);
822
823  /**
824   * 根据传入的参数实现卡尺和旗子的快捷跳转
825   * @param list 要跳转的数组
826   * @param type 标记类型(卡尺和旗子)
827   * @param direction 跳转方向(前一个/后一个)
828   */
829  MarkJump(list: Array<any>, type: string, direction: string): void {
830    this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet');
831    let find = list.find((it) => it.selected);
832    if (!find) {
833      // 如果当前没有选中的,就选中第一个
834      list.forEach((it) => (it.selected = false));
835      list[0].selected = true;
836    } else {
837      for (let i = 0; i < list.length; i++) {
838        // 将当前数组中选中的那条数据改为未选中
839        if (list[i].selected) {
840          list[i].selected = false;
841          if (direction === 'previous') {
842            if (i === 0) {
843              // 如果当前选中的是第一个,就循环到最后一个上
844              list[list.length - 1].selected = true;
845              break;
846            } else {
847              // 选中当前的上一个
848              list[i - 1].selected = true;
849              break;
850            }
851          } else if (direction === 'next') {
852            if (i === list.length - 1) {
853              // 如果当前选中的是最后一个,就循环到第一个上
854              list[0].selected = true;
855              break;
856            } else {
857              // 选中当前的下一个
858              list[i + 1].selected = true;
859              break;
860            }
861          }
862        }
863      }
864    }
865
866    if (type === 'flag') {
867      let currentPane = this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag');
868      list.forEach((flag, index) => {
869        this.timerShaftEL!.sportRuler!.drawTriangle(flag.time, flag.type);
870        if (flag.selected) {
871          // 修改当前选中的旗子对应的表格中某行的背景
872          currentPane!.setTableSelection(index + 1);
873        }
874      });
875    } else if (type === 'slice') {
876      this.refreshCanvas(true);
877      let currentPane = this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current');
878      list.forEach((slice, index) => {
879        if (slice.selected) {
880          // 修改当前选中的卡尺对应的表格中某行的背景
881          currentPane!.setTableSelection(index + 1);
882        }
883      });
884    }
885  }
886
887  isMouseInSheet = (ev: MouseEvent) => {
888    this.isMousePointInSheet =
889      this.traceSheetEL?.getAttribute('mode') != 'hidden' &&
890      ev.offsetX > this.traceSheetEL!.offsetLeft &&
891      ev.offsetY > this.traceSheetEL!.offsetTop;
892    return this.isMousePointInSheet;
893  };
894
895  favoriteChangeHandler = (row: TraceRow<any>): void => {
896    info('favoriteChangeHandler', row.frame, row.offsetTop, row.offsetHeight);
897  };
898
899  verticalScrollHandler = (row: TraceRow<any>): void => {
900    row.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
901  };
902
903  /**
904   * 根据选择的traceRow 处理foler
905   * @param currentRow 当前点击checkbox的row
906   */
907  setParentCheckStatus(currentRow: TraceRow<any>): void {
908    if (currentRow.parentRowEl?.folder && currentRow.parentRowEl?.childrenList) {
909      const parent = currentRow.parentRowEl;
910      const childrenList = parent.childrenList;
911      const selectList = [];
912      const unSelectList = [];
913      for (const child of childrenList) {
914        if (child.offsetParent === null) {
915          continue;
916        }
917        if (child.checkType === '2') {
918          selectList.push(child);
919        } else {
920          unSelectList.push(child);
921        }
922      }
923      if (unSelectList.length === 0) {
924        parent.setAttribute('check-type', '2');
925        parent.rangeSelect = true;
926        parent.checkBoxEL!.checked = true;
927        parent.checkBoxEL!.indeterminate = false;
928      } else if (selectList.length === 0) {
929        parent.setAttribute('check-type', '0');
930        parent.rangeSelect = false;
931        parent.checkBoxEL!.checked = false;
932        parent.checkBoxEL!.indeterminate = false;
933      } else {
934        parent.setAttribute('check-type', '1');
935        parent.rangeSelect = false;
936        parent.checkBoxEL!.checked = false;
937        parent.checkBoxEL!.indeterminate = true;
938      }
939    }
940  }
941
942  /**
943   * 处理点击checkbox的逻辑
944   * @param row 当前点击checkbox的row
945   */
946  selectChangeHandler = (row: TraceRow<any>): void => {
947    this.setParentCheckStatus(row);
948    const rows = [
949      ...this.shadowRoot!.querySelectorAll<TraceRow<any>>("trace-row[check-type='2']"),
950      ...this.favoriteChartListEL!.getAllSelectCollectRows(),
951    ];
952    this.isSelectClick = true;
953    this.rangeSelect.rangeTraceRow = rows;
954    let changeTraceRows: Array<TraceRow<any>> = [];
955    if (this.rangeTraceRow!.length < rows.length) {
956      rows!.forEach((currentTraceRow: TraceRow<any>) => {
957        let changeFilter = this.rangeTraceRow!.filter(
958          (prevTraceRow: TraceRow<any>) => prevTraceRow === currentTraceRow
959        );
960        if (changeFilter.length < 1) {
961          changeTraceRows.push(currentTraceRow);
962        }
963      });
964      if (changeTraceRows.length > 0) {
965        changeTraceRows!.forEach((changeTraceRow: TraceRow<any>) => {
966          let pointEvent = this.createPointEvent(changeTraceRow);
967          SpStatisticsHttpUtil.addOrdinaryVisitAction({
968            action: 'trace_row',
969            event: pointEvent,
970          });
971        });
972      }
973    }
974    this.rangeTraceRow = rows;
975    this.rangeSelect.selectHandler?.(this.rangeSelect.rangeTraceRow, false);
976  };
977  inFavoriteArea: boolean | undefined;
978  documentOnMouseMove = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseMove(this, ev);
979
980  hoverStructNull() {
981    CpuStruct.hoverCpuStruct = undefined;
982    CpuFreqStruct.hoverCpuFreqStruct = undefined;
983    ThreadStruct.hoverThreadStruct = undefined;
984    FuncStruct.hoverFuncStruct = undefined;
985    HiPerfCpuStruct.hoverStruct = undefined;
986    HiPerfProcessStruct.hoverStruct = undefined;
987    HiPerfThreadStruct.hoverStruct = undefined;
988    HiPerfEventStruct.hoverStruct = undefined;
989    HiPerfReportStruct.hoverStruct = undefined;
990    CpuStateStruct.hoverStateStruct = undefined;
991    CpuAbilityMonitorStruct.hoverCpuAbilityStruct = undefined;
992    DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined;
993    MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = undefined;
994    NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = undefined;
995    CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined;
996    FpsStruct.hoverFpsStruct = undefined;
997    ClockStruct.hoverClockStruct = undefined;
998    IrqStruct.hoverIrqStruct = undefined;
999    HeapStruct.hoverHeapStruct = undefined;
1000    JankStruct.hoverJankStruct = undefined;
1001    AppStartupStruct.hoverStartupStruct = undefined;
1002    SoStruct.hoverSoStruct = undefined;
1003    HeapSnapshotStruct.hoverSnapshotStruct = undefined;
1004    FrameAnimationStruct.hoverFrameAnimationStruct = undefined;
1005    FrameDynamicStruct.hoverFrameDynamicStruct = undefined;
1006    FrameSpacingStruct.hoverFrameSpacingStruct = undefined;
1007    JsCpuProfilerStruct.hoverJsCpuProfilerStruct = undefined;
1008    SnapshotStruct.hoverSnapshotStruct = undefined;
1009    HiPerfCallChartStruct.hoverPerfCallCutStruct = undefined;
1010    this.tipEL!.style.display = 'none';
1011    return this;
1012  }
1013
1014  selectStructNull() {
1015    CpuStruct.selectCpuStruct = undefined;
1016    CpuStruct.wakeupBean = null;
1017    CpuFreqStruct.selectCpuFreqStruct = undefined;
1018    ThreadStruct.selectThreadStruct = undefined;
1019    FuncStruct.selectFuncStruct = undefined;
1020    SpHiPerf.selectCpuStruct = undefined;
1021    CpuStateStruct.selectStateStruct = undefined;
1022    CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = undefined;
1023    ClockStruct.selectClockStruct = undefined;
1024    IrqStruct.selectIrqStruct = undefined;
1025    JankStruct.selectJankStruct = undefined;
1026    HeapStruct.selectHeapStruct = undefined;
1027    AppStartupStruct.selectStartupStruct = undefined;
1028    SoStruct.selectSoStruct = undefined;
1029    HeapSnapshotStruct.selectSnapshotStruct = undefined;
1030    FrameSpacingStruct.selectFrameSpacingStruct = undefined;
1031    FrameAnimationStruct.selectFrameAnimationStruct = undefined;
1032    FrameDynamicStruct.selectFrameDynamicStruct = undefined;
1033    JsCpuProfilerStruct.selectJsCpuProfilerStruct = undefined;
1034    SnapshotStruct.selectSnapshotStruct = undefined;
1035    HiPerfCallChartStruct.selectStruct = undefined;
1036    AllAppStartupStruct.selectStartupStruct = undefined;
1037    LtpoStruct.selectLtpoStruct = undefined;
1038    HitchTimeStruct.selectHitchTimeStruct = undefined;
1039    return this;
1040  }
1041
1042  isWASDKeyPress() {
1043    return (
1044      this.keyPressMap.get('w') || this.keyPressMap.get('a') || this.keyPressMap.get('d') || this.keyPressMap.get('s')
1045    );
1046  }
1047
1048  documentOnClick = (ev: MouseEvent) => spSystemTraceDocumentOnClick(this, ev);
1049
1050  clickEmptyArea() {
1051    this.queryAllTraceRow().forEach((it) => {
1052      it.checkType = '-1';
1053      it.rangeSelect = false;
1054    });
1055    this.rangeSelect.rangeTraceRow = [];
1056    TraceRow.rangeSelectObject = undefined;
1057    this.selectStructNull();
1058    this.wakeupListNull();
1059    this.observerScrollHeightEnable = false;
1060    this.selectFlag = null;
1061    this.timerShaftEL?.removeTriangle('inverted');
1062    //   如果鼠标在SportRuler区域不隐藏tab页
1063    if (!SportRuler.isMouseInSportRuler) {
1064      this.traceSheetEL?.setAttribute('mode', 'hidden');
1065    }
1066    this.removeLinkLinesByBusinessType('task', 'thread');
1067    this.refreshCanvas(true);
1068    JankStruct.delJankLineFlag = true;
1069  }
1070
1071  //泳道图点击判定条件
1072  traceRowClickJudgmentConditions: Map<string, () => boolean> = new Map<string, () => boolean>([
1073    [TraceRow.ROW_TYPE_CPU, (): boolean => CpuStruct.hoverCpuStruct !== null && CpuStruct.hoverCpuStruct !== undefined],
1074    [
1075      TraceRow.ROW_TYPE_THREAD,
1076      (): boolean => ThreadStruct.hoverThreadStruct !== null && ThreadStruct.hoverThreadStruct !== undefined,
1077    ],
1078    [
1079      TraceRow.ROW_TYPE_FUNC,
1080      (): boolean => FuncStruct.hoverFuncStruct !== null && FuncStruct.hoverFuncStruct !== undefined,
1081    ],
1082    [
1083      TraceRow.ROW_TYPE_CPU_FREQ,
1084      (): boolean => CpuFreqStruct.hoverCpuFreqStruct !== null && CpuFreqStruct.hoverCpuFreqStruct !== undefined,
1085    ],
1086    [
1087      TraceRow.ROW_TYPE_CPU_STATE,
1088      (): boolean => CpuStateStruct.hoverStateStruct !== null && CpuStateStruct.hoverStateStruct !== undefined,
1089    ],
1090    [
1091      TraceRow.ROW_TYPE_CPU_FREQ_LIMIT,
1092      (): boolean =>
1093        CpuFreqLimitsStruct.selectCpuFreqLimitsStruct !== null &&
1094        CpuFreqLimitsStruct.selectCpuFreqLimitsStruct !== undefined,
1095    ],
1096    [
1097      TraceRow.ROW_TYPE_CLOCK,
1098      (): boolean => ClockStruct.hoverClockStruct !== null && ClockStruct.hoverClockStruct !== undefined,
1099    ],
1100    [TraceRow.ROW_TYPE_IRQ, (): boolean => IrqStruct.hoverIrqStruct !== null && IrqStruct.hoverIrqStruct !== undefined],
1101    [
1102      TraceRow.ROW_TYPE_APP_STARTUP,
1103      (): boolean => AppStartupStruct.hoverStartupStruct !== null && AppStartupStruct.hoverStartupStruct !== undefined,
1104    ],
1105    [
1106      TraceRow.ROW_TYPE_ALL_APPSTARTUPS,
1107      (): boolean =>
1108        AllAppStartupStruct.hoverStartupStruct !== null && AllAppStartupStruct.hoverStartupStruct !== undefined,
1109    ],
1110    [TraceRow.ROW_TYPE_STATIC_INIT, () => SoStruct.hoverSoStruct !== null && SoStruct.hoverSoStruct !== undefined],
1111    [TraceRow.ROW_TYPE_JANK, () => JankStruct.hoverJankStruct !== null && JankStruct.hoverJankStruct !== undefined],
1112    [TraceRow.ROW_TYPE_HEAP, () => HeapStruct.hoverHeapStruct !== null && HeapStruct.hoverHeapStruct !== undefined],
1113    [
1114      TraceRow.ROW_TYPE_SYS_MEMORY_GPU_TOTAL,
1115      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1116    ],
1117    [
1118      TraceRow.ROW_TYPE_SYS_MEMORY_GPU_WINDOW,
1119      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1120    ],
1121    [
1122      TraceRow.ROW_TYPE_HEAP_SNAPSHOT,
1123      (): boolean =>
1124        HeapSnapshotStruct.hoverSnapshotStruct !== null && HeapSnapshotStruct.hoverSnapshotStruct !== undefined,
1125    ],
1126    [
1127      TraceRow.ROW_TYPE_FRAME_ANIMATION,
1128      (): boolean =>
1129        FrameAnimationStruct.hoverFrameAnimationStruct !== null &&
1130        FrameAnimationStruct.hoverFrameAnimationStruct !== undefined,
1131    ],
1132    [
1133      TraceRow.ROW_TYPE_FRAME_DYNAMIC,
1134      (): boolean =>
1135        FrameDynamicStruct.hoverFrameDynamicStruct !== null && FrameDynamicStruct.hoverFrameDynamicStruct !== undefined,
1136    ],
1137    [
1138      TraceRow.ROW_TYPE_FRAME_SPACING,
1139      (): boolean =>
1140        FrameSpacingStruct.hoverFrameSpacingStruct !== null && FrameSpacingStruct.hoverFrameSpacingStruct !== undefined,
1141    ],
1142    [
1143      TraceRow.ROW_TYPE_JS_CPU_PROFILER,
1144      (): boolean =>
1145        JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== null &&
1146        JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== undefined,
1147    ],
1148    [
1149      TraceRow.ROW_TYPE_PURGEABLE_TOTAL_ABILITY,
1150      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1151    ],
1152    [
1153      TraceRow.ROW_TYPE_PURGEABLE_PIN_ABILITY,
1154      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1155    ],
1156    [
1157      TraceRow.ROW_TYPE_PURGEABLE_TOTAL_VM,
1158      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1159    ],
1160    [
1161      TraceRow.ROW_TYPE_PURGEABLE_PIN_VM,
1162      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1163    ],
1164    [
1165      TraceRow.ROW_TYPE_DMA_ABILITY,
1166      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1167    ],
1168    [
1169      TraceRow.ROW_TYPE_DMA_VMTRACKER,
1170      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1171    ],
1172    [
1173      TraceRow.ROW_TYPE_GPU_MEMORY_ABILITY,
1174      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1175    ],
1176    [
1177      TraceRow.ROW_TYPE_GPU_MEMORY_VMTRACKER,
1178      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1179    ],
1180    [
1181      TraceRow.ROW_TYPE_GPU_RESOURCE_VMTRACKER,
1182      () => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1183    ],
1184    [
1185      TraceRow.ROW_TYPE_VMTRACKER_SHM,
1186      () => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1187    ],
1188    [
1189      TraceRow.ROW_TYPE_VM_TRACKER_SMAPS,
1190      () => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1191    ],
1192    [TraceRow.ROW_TYPE_LOGS, () => LogStruct.hoverLogStruct !== null && LogStruct.hoverLogStruct !== undefined],
1193  ]);
1194
1195  onClickHandler(clickRowType: string, row?: TraceRow<any>) {
1196    spSystemTraceOnClickHandler(this, clickRowType, row);
1197  }
1198
1199  makePoint(
1200    ts: number,
1201    dur: number,
1202    translateY: number,
1203    rowStruct: any,
1204    offsetY: number,
1205    business: string,
1206    lineType: LineType,
1207    isRight: boolean
1208  ): PairPoint {
1209    return {
1210      x: ns2xByTimeShaft(ts + dur, this.timerShaftEL!),
1211      y: translateY!,
1212      offsetY: offsetY,
1213      ns: ts + dur,
1214      rowEL: rowStruct!,
1215      isRight: isRight,
1216      business: business,
1217      lineType: lineType,
1218    };
1219  }
1220
1221  drawTaskPollLine(row?: TraceRow<any>) {
1222    spSystemTraceDrawTaskPollLine(this, row);
1223  }
1224  drawJankLine(endParentRow: any, selectJankStruct: JankStruct, data: any) {
1225    spSystemTraceDrawJankLine(this, endParentRow, selectJankStruct, data);
1226  }
1227
1228  drawThreadLine(endParentRow: any, selectThreadStruct: ThreadStruct | undefined, data: any) {
1229    spSystemTraceDrawThreadLine(this, endParentRow, selectThreadStruct, data);
1230  }
1231
1232  getStartRow(selectRowId: number | undefined, collectList: any[]): any {
1233    let startRow = this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>(
1234      `trace-row[row-id='${selectRowId}'][row-type='thread']`
1235    );
1236    if (!startRow) {
1237      for (let collectChart of collectList) {
1238        if (collectChart.rowId === selectRowId?.toString() && collectChart.rowType === 'thread') {
1239          startRow = collectChart;
1240          break;
1241        }
1242      }
1243    }
1244    return startRow;
1245  }
1246
1247  calculateStartY(startRow: any, selectThreadStruct: ThreadStruct): [number, any, number] {
1248    let startY = startRow!.translateY!;
1249    let startRowEl = startRow;
1250    let startOffSetY = 20 * 0.5;
1251    const startParentRow = this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>(
1252      `trace-row[row-id='${startRow.rowParentId}'][folder]`
1253    );
1254    const expansionFlag = this.collectionHasThread(startRow);
1255    if (startParentRow && !startParentRow.expansion && expansionFlag) {
1256      startY = startParentRow.translateY!;
1257      startRowEl = startParentRow;
1258      startOffSetY = 10 * 0.5;
1259    }
1260    return [startY, startRowEl, startOffSetY];
1261  }
1262
1263  calculateEndY(endParentRow: any, endRowStruct: any): [number, any, number] {
1264    let endY = endRowStruct.translateY!;
1265    let endRowEl = endRowStruct;
1266    let endOffSetY = 20 * 0.5;
1267    const expansionFlag = this.collectionHasThread(endRowStruct);
1268    if (!endParentRow.expansion && expansionFlag) {
1269      endY = endParentRow.translateY!;
1270      endRowEl = endParentRow;
1271      endOffSetY = 10 * 0.5;
1272    }
1273    return [endY, endRowEl, endOffSetY];
1274  }
1275
1276  collectionHasThread(threadRow: any): boolean {
1277    const collectList = this.favoriteChartListEL!.getCollectRows();
1278    for (let item of collectList!) {
1279      if (item.rowId === threadRow.rowId && item.rowType === threadRow.rowType) {
1280        return false;
1281      }
1282    }
1283    return true;
1284  }
1285
1286  translateByMouseMove(ev: MouseEvent): void {
1287    ev.preventDefault();
1288    let offset = 0;
1289    if (this.offsetMouse === 0) {
1290      this.offsetMouse = ev.clientX;
1291      offset = ev.clientX - this.mouseCurrentPosition;
1292    } else {
1293      offset = ev.clientX - this.offsetMouse;
1294    }
1295    this.offsetMouse = ev.clientX;
1296    const rangeRuler = this.timerShaftEL?.getRangeRuler()!;
1297
1298    rangeRuler.translate(offset);
1299  }
1300
1301  private eventListener(): void {
1302    /**
1303     * 监听时间轴区间变化
1304     */
1305    this.timerShaftEL!.rangeChangeHandler = this.timerShaftELRangeChange;
1306    this.timerShaftEL!.rangeClickHandler = this.timerShaftELRangeClick;
1307    this.timerShaftEL!.flagChangeHandler = this.timerShaftELFlagChange;
1308    this.timerShaftEL!.flagClickHandler = this.timerShaftELFlagClickHandler;
1309    /**
1310     * 监听rowsEL的滚动时间,刷新可见区域的trace-row组件的时间区间(将触发trace-row组件重绘)
1311     */
1312    this.rowsPaneEL?.addEventListener('scroll', this.rowsElOnScroll, {
1313      passive: true,
1314    });
1315    this.favoriteChartListEL?.addEventListener('scroll', this.favoriteRowsElOnScroll, {
1316      passive: true,
1317    });
1318    /**
1319     * 监听document的mousemove事件 坐标通过换算后找到当前鼠标所在的trace-row组件,将坐标传入
1320     */
1321    this.addEventListener('mousemove', this.documentOnMouseMove);
1322    this.addEventListener('click', this.documentOnClick);
1323    this.addEventListener('mousedown', this.documentOnMouseDown);
1324    this.addEventListener('mouseup', this.documentOnMouseUp);
1325    this.addEventListener('mouseout', this.documentOnMouseOut);
1326
1327    document.addEventListener('keydown', this.documentOnKeyDown);
1328    document.addEventListener('keypress', this.documentOnKeyPress);
1329    document.addEventListener('keyup', this.documentOnKeyUp);
1330    document.addEventListener('contextmenu', this.onContextMenuHandler);
1331    this.wheelListener();
1332  }
1333
1334  private wheelListener() {
1335    document.addEventListener(
1336      'wheel',
1337      (e) => {
1338        if (e.ctrlKey) {
1339          if (e.deltaY > 0) {
1340            e.preventDefault();
1341            e.stopPropagation();
1342            let eventS = new KeyboardEvent('keypress', {
1343              key: 's',
1344              code: '83',
1345              keyCode: 83,
1346            });
1347            this.timerShaftEL!.documentOnKeyPress(eventS);
1348            setTimeout(() => {
1349              this.timerShaftEL!.documentOnKeyUp(eventS);
1350            }, 200);
1351          }
1352          if (e.deltaY < 0) {
1353            e.preventDefault();
1354            e.stopPropagation();
1355            let eventW = new KeyboardEvent('keypress', {
1356              key: 'w',
1357              code: '87',
1358              keyCode: 87,
1359            });
1360            this.timerShaftEL!.documentOnKeyPress(eventW);
1361            setTimeout(() => {
1362              this.timerShaftEL!.documentOnKeyUp(eventW);
1363            }, 200);
1364          }
1365        }
1366      },
1367      { passive: false }
1368    );
1369  }
1370
1371  connectedCallback(): void {
1372    this.initPointToEvent();
1373    this.eventListener();
1374    /**
1375     * 泳道图中添加ctrl+鼠标滚轮事件,对泳道图进行放大缩小。
1376     * 鼠标滚轮事件转化为键盘事件,keyPress和keyUp两个事件需要配合使用,
1377     * 否则泳道图会一直放大或一直缩小。
1378     * setTimeout()函数中的时间参数可以控制鼠标滚轮的频率。
1379     */
1380    SpApplication.skinChange2 = (val: boolean) => {
1381      this.timerShaftEL?.render();
1382    };
1383    window.subscribe(window.SmartEvent.UI.UploadSOFile, (data) => {
1384      this.chartManager?.importSoFileUpdate().then(() => {
1385        window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Import So File' });
1386        let updateCanvas = this.traceSheetEL?.updateRangeSelect();
1387        if (updateCanvas) {
1388          this.refreshCanvas(true);
1389        }
1390      });
1391    });
1392
1393    window.subscribe(window.SmartEvent.UI.KeyPath, (data) => {
1394      this.invisibleRows.forEach((it) => (it.needRefresh = true));
1395      this.visibleRows.forEach((it) => (it.needRefresh = true));
1396      if (data.length === 0) {
1397        // clear
1398        SpSystemTrace.keyPathList = [];
1399        this.refreshCanvas(false);
1400      } else {
1401        // draw
1402        queryCpuKeyPathData(data).then((res) => {
1403          SpSystemTrace.keyPathList = res;
1404          this.refreshCanvas(false);
1405        });
1406      }
1407    });
1408
1409    window.subscribe(window.SmartEvent.UI.CheckALL, (data) => {
1410      this.getCollectRows((row) => row.rowParentId === data.rowId).forEach((it) => {
1411        it.checkType = data.isCheck ? '2' : '0';
1412      });
1413    });
1414    window.subscribe(window.SmartEvent.UI.HoverNull, () => this.hoverStructNull());
1415  }
1416
1417  favoriteAreaSearchHandler(row: TraceRow<any>): void {
1418    if (this.timerShaftEL!.collecBtn!.hasAttribute('close')) {
1419      this.timerShaftEL!.collecBtn!.removeAttribute('close');
1420      this.favoriteChartListEL!.showCollectArea();
1421    }
1422    this.favoriteChartListEL?.expandSearchRowGroup(row);
1423  }
1424
1425  scrollToProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) {
1426    let traceRow =
1427      this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`) ||
1428      this.favoriteChartListEL!.getCollectRow((row) => row.rowId === rowId && row.rowType === rowType);
1429    if (traceRow?.collect) {
1430      this.favoriteChartListEL!.scroll({
1431        top:
1432          (traceRow?.offsetTop || 0) -
1433          this.favoriteChartListEL!.getCanvas()!.offsetHeight +
1434          (traceRow?.offsetHeight || 0),
1435        left: 0,
1436        behavior: smooth ? 'smooth' : undefined,
1437      });
1438    } else {
1439      let row = this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`);
1440      if (row && !row.expansion) {
1441        row.expansion = true;
1442      }
1443      if (traceRow && traceRow.offsetTop >= 0 && traceRow.offsetHeight >= 0) {
1444        this.rowsPaneEL!.scroll({
1445          top: (traceRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + (traceRow?.offsetHeight || 0),
1446          left: 0,
1447          behavior: smooth ? 'smooth' : undefined,
1448        });
1449      }
1450    }
1451  }
1452
1453  scrollToDepth(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true, depth: number) {
1454    let rootRow =
1455      this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`) ||
1456      this.favoriteChartListEL!.getCollectRow((row) => row.rowId === rowId && row.rowType === rowType);
1457    if (rootRow && rootRow!.collect) {
1458      this.favoriteAreaSearchHandler(rootRow);
1459      rootRow.expandFunc();
1460      this.favoriteChartListEL!.scroll({
1461        top: (rootRow?.offsetTop || 0) - this.favoriteChartListEL!.getCanvas()!.offsetHeight + (++depth * 20 || 0),
1462        left: 0,
1463        behavior: smooth ? 'smooth' : undefined,
1464      });
1465    } else {
1466      let row = this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`);
1467      if (row && !row.expansion) {
1468        row.expansion = true;
1469      }
1470      if (rootRow) {
1471        rootRow.expandFunc();
1472      }
1473      if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) {
1474        let top = (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + (++depth * 20 || 0);
1475        this.rowsPaneEL!.scroll({
1476          top: top,
1477          left: 0,
1478          behavior: smooth ? 'smooth' : undefined,
1479        });
1480      }
1481    }
1482  }
1483
1484  scrollToFunction(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) {
1485    let condition = `trace-row[row-id='${rowId}'][row-type='${rowType}'][row-parent-id='${rowParentId}']`;
1486    let rootRow =
1487      this.rowsEL!.querySelector<TraceRow<any>>(condition) ||
1488      this.favoriteChartListEL!.getCollectRow((row) => {
1489        return row.rowId === rowId && row.rowType === rowType && row.rowParentId === rowParentId;
1490      });
1491    if (rootRow?.collect) {
1492      this.favoriteAreaSearchHandler(rootRow);
1493      this.favoriteChartListEL!.scroll({
1494        top:
1495          (rootRow?.offsetTop || 0) -
1496          this.favoriteChartListEL!.getCanvas()!.offsetHeight +
1497          (rootRow?.offsetHeight || 0),
1498        left: 0,
1499        behavior: smooth ? 'smooth' : undefined,
1500      });
1501    } else {
1502      let row = this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`);
1503      if (row && !row.expansion) {
1504        row.expansion = true;
1505      }
1506      if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) {
1507        this.rowsPaneEL!.scroll({
1508          top: (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + 20,
1509          left: 0,
1510          behavior: smooth ? 'smooth' : undefined,
1511        });
1512      }
1513    }
1514  }
1515
1516  disconnectedCallback() {
1517    this.timerShaftEL?.removeEventListener('range-change', this.timerShaftELRangeChange);
1518    this.rowsPaneEL?.removeEventListener('scroll', this.rowsElOnScroll);
1519    this.favoriteChartListEL?.removeEventListener('scroll', this.favoriteRowsElOnScroll);
1520    this.removeEventListener('mousemove', this.documentOnMouseMove);
1521    this.removeEventListener('click', this.documentOnClick);
1522    this.removeEventListener('mousedown', this.documentOnMouseDown);
1523    this.removeEventListener('mouseup', this.documentOnMouseUp);
1524    this.removeEventListener('mouseout', this.documentOnMouseOut);
1525    document.removeEventListener('keypress', this.documentOnKeyPress);
1526    document.removeEventListener('keydown', this.documentOnKeyDown);
1527    document.removeEventListener('keyup', this.documentOnKeyUp);
1528    document.removeEventListener('contextmenu', this.onContextMenuHandler);
1529    window.unsubscribe(window.SmartEvent.UI.SliceMark, this.sliceMarkEventHandler.bind(this));
1530  }
1531
1532  sliceMarkEventHandler(ev: any) {
1533    SpSystemTrace.sliceRangeMark = ev;
1534    let startNS = ev.timestamp - (window as any).recordStartNS;
1535    let endNS = ev.maxDuration + startNS;
1536    TraceRow.rangeSelectObject = {
1537      startX: 0,
1538      startNS: startNS,
1539      endNS: endNS,
1540      endX: 0,
1541    };
1542    window.publish(window.SmartEvent.UI.MenuTrace, {});
1543    window.publish(window.SmartEvent.UI.TimeRange, {
1544      startNS: startNS - ev.maxDuration,
1545      endNS: endNS + ev.maxDuration,
1546    });
1547    this.queryAllTraceRow().forEach((it) => (it.checkType = '-1'));
1548    this.rangeSelect.rangeTraceRow = [];
1549    this.selectStructNull();
1550    this.wakeupListNull();
1551    this.traceSheetEL?.setAttribute('mode', 'hidden');
1552    this.removeLinkLinesByBusinessType('janks');
1553    TraceRow.range!.refresh = true;
1554    this.refreshCanvas(false);
1555  }
1556
1557  loadDatabaseUrl(
1558    url: string,
1559    progress: Function,
1560    complete?: ((res: { status: boolean; msg: string }) => void) | undefined
1561  ) {
1562    this.observerScrollHeightEnable = false;
1563    this.init({ url: url }, '', progress).then((res) => {
1564      if (complete) {
1565        complete(res);
1566        window.publish(window.SmartEvent.UI.MouseEventEnable, {
1567          mouseEnable: true,
1568        });
1569      }
1570    });
1571  }
1572
1573  loadDatabaseArrayBuffer(
1574    buf: ArrayBuffer,
1575    thirdPartyWasmConfigUrl: string,
1576    progress: (name: string, percent: number) => void,
1577    complete?: ((res: { status: boolean; msg: string }) => void) | undefined
1578  ) {
1579    this.observerScrollHeightEnable = false;
1580    this.init({ buf }, thirdPartyWasmConfigUrl, progress).then((res) => {
1581      this.rowsEL?.querySelectorAll('trace-row').forEach((it: any) => this.observer.observe(it));
1582      if (complete) {
1583        complete(res);
1584        window.publish(window.SmartEvent.UI.MouseEventEnable, {
1585          mouseEnable: true,
1586        });
1587      }
1588    });
1589  }
1590
1591  queryAllTraceRow<T>(selectors?: string, filter?: (row: TraceRow<any>) => boolean): TraceRow<any>[] {
1592    return [
1593      ...this.rowsEL!.querySelectorAll<TraceRow<any>>(selectors ?? 'trace-row'),
1594      ...this.favoriteChartListEL!.getCollectRows(filter),
1595    ];
1596  }
1597
1598  search(query: string) {
1599    this.queryAllTraceRow().forEach((item) => {
1600      if (query == null || query == undefined || query == '') {
1601        if (
1602          item.rowType == TraceRow.ROW_TYPE_CPU ||
1603          item.rowType == TraceRow.ROW_TYPE_CPU_FREQ ||
1604          item.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY ||
1605          item.rowType == TraceRow.ROW_TYPE_FPS ||
1606          item.rowType == TraceRow.ROW_TYPE_PROCESS ||
1607          item.rowType == TraceRow.ROW_TYPE_CPU_ABILITY ||
1608          item.rowType == TraceRow.ROW_TYPE_MEMORY_ABILITY ||
1609          item.rowType == TraceRow.ROW_TYPE_DISK_ABILITY ||
1610          item.rowType == TraceRow.ROW_TYPE_NETWORK_ABILITY
1611        ) {
1612          item.expansion = false;
1613          item.rowHidden = false;
1614        } else {
1615          item.rowHidden = true;
1616        }
1617      } else {
1618        item.rowHidden = item.name.toLowerCase().indexOf(query.toLowerCase()) < 0;
1619      }
1620    });
1621    this.visibleRows.forEach((it) => (it.rowHidden = false && it.draw(true)));
1622  }
1623
1624  async searchCPU(query: string): Promise<Array<any>> {
1625    let pidArr: Array<number> = [];
1626    let tidArr: Array<number> = [];
1627    for (let key of Utils.PROCESS_MAP.keys()) {
1628      if (`${key}`.includes(query) || (Utils.PROCESS_MAP.get(key) || '').includes(query)) {
1629        pidArr.push(key);
1630      }
1631    }
1632    for (let key of Utils.THREAD_MAP.keys()) {
1633      if (`${key}`.includes(query) || (Utils.THREAD_MAP.get(key) || '').includes(query)) {
1634        tidArr.push(key);
1635      }
1636    }
1637    return await searchCpuDataSender(pidArr, tidArr);
1638  }
1639
1640  async searchFunction(cpuList: Array<any>, query: string): Promise<Array<any>> {
1641    let processList: Array<string> = [];
1642    let traceRow =
1643      this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[scene]`) ||
1644      this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene'));
1645    if (traceRow) {
1646      this.shadowRoot!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='process'][scene]`).forEach((row) => {
1647        processList.push(row.rowId!);
1648      });
1649      if (query.includes('_')) {
1650        query = query.replace(/_/g, '\\_');
1651      }
1652      if (query.includes('%')) {
1653        query = query.replace(/%/g, '\\%');
1654      }
1655      let list = await querySceneSearchFunc(query, processList);
1656      cpuList = cpuList.concat(list);
1657      cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0));
1658      return cpuList;
1659    } else {
1660      let list = await querySearchFunc(query);
1661      cpuList = cpuList.concat(list);
1662      cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0));
1663      return cpuList;
1664    }
1665  }
1666
1667  searchSdk(dataList: Array<any>, query: string): Array<any> {
1668    let traceRow =
1669      this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[scene]`) ||
1670      this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene'));
1671    let dataAll = `trace-row[row-type^='sdk']`;
1672    if (traceRow) {
1673      dataAll = `trace-row[row-type^='sdk'][scene]`;
1674    }
1675    let allTraceRow: any = [];
1676    let parentRows = this.shadowRoot!.querySelectorAll<TraceRow<any>>(`${dataAll}`);
1677    parentRows.forEach((parentRow: TraceRow<any>) => {
1678      allTraceRow.push(parentRow);
1679      if (parentRow.childrenList && parentRow.childrenList.length > 0) {
1680        allTraceRow.push(...parentRow.childrenList);
1681      }
1682    });
1683    allTraceRow.forEach((row: any) => {
1684      if (row!.name.indexOf(query) >= 0) {
1685        let searchSdkBean = new SearchSdkBean();
1686        searchSdkBean.startTime = TraceRow.range!.startNS;
1687        searchSdkBean.dur = TraceRow.range!.totalNS;
1688        searchSdkBean.name = row.name;
1689        searchSdkBean.rowId = row.rowId;
1690        searchSdkBean.type = 'sdk';
1691        searchSdkBean.rowType = row.rowType;
1692        searchSdkBean.rowParentId = row.rowParentId;
1693        dataList.push(searchSdkBean);
1694      }
1695    });
1696    return dataList;
1697  }
1698
1699  showStruct(previous: boolean, currentIndex: number, structs: Array<any>, retargetIndex?: number) {
1700    return spSystemTraceShowStruct(this, previous, currentIndex, structs, retargetIndex);
1701  }
1702
1703  private toTargetDepth = (entry: any, funcRowID: number, funcStract: any) => {
1704    if (entry) {
1705      this.hoverStructNull();
1706      this.selectStructNull();
1707      this.wakeupListNull();
1708      FuncStruct.hoverFuncStruct = entry;
1709      FuncStruct.selectFuncStruct = entry;
1710      this.onClickHandler(TraceRow.ROW_TYPE_FUNC);
1711      this.scrollToDepth(`${funcRowID}`, `${funcStract.pid}`, 'func', true, entry.depth || 0);
1712    }
1713  };
1714
1715  scrollToActFunc(funcStract: any, highlight: boolean): void {
1716    if (!Utils.isBinder(funcStract)) {
1717      if (funcStract.dur === -1 || funcStract.dur === null || funcStract.dur === undefined) {
1718        funcStract.dur = (TraceRow.range?.totalNS || 0) - (funcStract.startTs || 0);
1719        funcStract.flag = 'Did not end';
1720      }
1721    }
1722
1723    let funcRowID = funcStract.cookie == null ? funcStract.tid : `${funcStract.funName}-${funcStract.pid}`;
1724    let targetRow = this.favoriteChartListEL?.getCollectRow((row) => {
1725      return row.rowId === funcRowID && row.rowType === 'func';
1726    });
1727    if (targetRow) {
1728      targetRow.fixedList[0] = funcStract;
1729      targetRow.highlight = highlight;
1730      //如果目标泳道图在收藏上面,则跳转至收藏
1731      this.toTargetDepth(funcStract, funcRowID, funcStract);
1732      return;
1733    }
1734    let parentRow = this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${funcStract.pid}'][folder]`);
1735    if (!parentRow) {
1736      return;
1737    }
1738    let filterRow = parentRow.childrenList.filter((child) => child.rowId == funcRowID && child.rowType == 'func')[0];
1739    if (filterRow == null) {
1740      let funcRow = this.rowsEL?.querySelector<TraceRow<any>>(`trace-row[row-id='${funcRowID}'][row-type='func']`);
1741      if (funcRow) {
1742        filterRow = funcRow;
1743      } else {
1744        return;
1745      }
1746    }
1747    filterRow.fixedList = [funcStract];
1748    filterRow!.highlight = highlight;
1749    let row = this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${funcStract.pid}'][folder]`);
1750    this.currentRow = row;
1751    if (row && !row.expansion) {
1752      row.expansion = true;
1753    }
1754    const completeEntry = () => {
1755      this.toTargetDepth(filterRow.fixedList[0], funcRowID, funcStract);
1756    };
1757    if (filterRow!.isComplete) {
1758      completeEntry();
1759    } else {
1760      this.scrollToProcess(`${funcStract.tid}`, `${funcStract.pid}`, 'thread', false);
1761      this.scrollToFunction(`${funcStract.tid}`, `${funcStract.pid}`, 'func', true);
1762      filterRow!.onComplete = completeEntry;
1763    }
1764  }
1765
1766  closeAllExpandRows(pid: string) {
1767    let expandRows = this.rowsEL?.querySelectorAll<TraceRow<ProcessStruct>>(`trace-row[row-type='process'][expansion]`);
1768    expandRows?.forEach((row) => {
1769      if (row.rowId != pid) {
1770        row.expansion = false;
1771      }
1772    });
1773  }
1774
1775  moveRangeToCenter(startTime: number, dur: number) {
1776    let startNS = this.timerShaftEL?.getRange()?.startNS || 0;
1777    let endNS = this.timerShaftEL?.getRange()?.endNS || 0;
1778    let harfDur = Math.trunc((endNS - startNS) / 2 - dur / 2);
1779    let leftNs = startTime - harfDur;
1780    let rightNs = startTime + dur + harfDur;
1781    if (startTime - harfDur < 0) {
1782      leftNs = 0;
1783      rightNs += harfDur - startTime;
1784    }
1785    this.timerShaftEL?.setRangeNS(leftNs, rightNs);
1786    TraceRow.range!.refresh = true;
1787    this.refreshCanvas(true);
1788  }
1789
1790  rechargeCpuData(it: CpuStruct, next: CpuStruct | undefined): void {
1791    let p = Utils.PROCESS_MAP.get(it.processId!);
1792    let t = Utils.THREAD_MAP.get(it.tid!);
1793    let slice = Utils.SCHED_SLICE_MAP.get(`${it.id}-${it.startTime}`);
1794    if (slice) {
1795      it.end_state = slice.endState;
1796      it.priority = slice.priority;
1797    }
1798    it.processName = p;
1799    it.processCmdLine = p;
1800    it.name = t;
1801    it.type = 'thread';
1802    if (next) {
1803      if (it.startTime! + it.dur! > next!.startTime! || it.dur == -1 || it.dur === null || it.dur === undefined) {
1804        it.dur = next!.startTime! - it.startTime!;
1805        it.nofinish = true;
1806      }
1807    } else {
1808      if (it.dur == -1 || it.dur === null || it.dur === undefined) {
1809        it.dur = TraceRow.range!.endNS - it.startTime!;
1810        it.nofinish = true;
1811      }
1812    }
1813  }
1814
1815  reset(progress: Function | undefined | null) {
1816    this.visibleRows.length = 0;
1817    this.tipEL!.style.display = 'none';
1818    this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.clientWidth, this.canvasPanel!.offsetHeight);
1819    this.loadTraceCompleted = false;
1820    this.collectRows = [];
1821    this.visibleRows = [];
1822    TraceRowConfig.allTraceRowList.forEach((it) => {
1823      it.clearMemory();
1824    });
1825    TraceRowConfig.allTraceRowList = [];
1826    this.favoriteChartListEL!.reset();
1827    if (this.rowsEL) {
1828      this.rowsEL.querySelectorAll<TraceRow<any>>(`trace-row`).forEach((row) => {
1829        row.clearMemory();
1830        this.rowsEL!.removeChild(row);
1831      });
1832    }
1833    this.traceSheetEL?.clearMemory();
1834    this.spacerEL!.style.height = '0px';
1835    this.rangeSelect.rangeTraceRow = [];
1836    SpSystemTrace.SDK_CONFIG_MAP = undefined;
1837    SpSystemTrace.sliceRangeMark = undefined;
1838    this.timerShaftEL?.displayCollect(false);
1839    this.timerShaftEL!.collecBtn!.removeAttribute('close');
1840    CpuStruct.wakeupBean = undefined;
1841    this.selectStructNull();
1842    this.hoverStructNull();
1843    this.wakeupListNull();
1844    this.traceSheetEL?.setAttribute('mode', 'hidden');
1845    progress?.('rest timershaft', 8);
1846    this.timerShaftEL?.reset();
1847    progress?.('clear cache', 10);
1848    HeapDataInterface.getInstance().clearData();
1849    procedurePool.clearCache();
1850    Utils.clearData();
1851    InitAnalysis.getInstance().isInitAnalysis = true;
1852    procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: any) => {});
1853    if (threadPool) {
1854      threadPool.submitProto(QueryEnum.ClearMemoryCache, {}, (res: any, len: number): void => {});
1855    }
1856    this.times.clear();
1857    resetVSync();
1858    SpSystemTrace.keyPathList = [];
1859  }
1860
1861  init = async (param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) => {
1862    return spSystemTraceInit(this, param, wasmConfigUri, progress);
1863  };
1864
1865  extracted(it: TraceRow<any>) {
1866    return () => {
1867      if (it.hasAttribute('expansion')) {
1868        it.childrenList.forEach((child) => {
1869          if (child.hasAttribute('scene') && !child.collect) {
1870            child.rowHidden = false;
1871          }
1872          if (child.folder) {
1873            child.addEventListener('expansion-change', this.extracted(child));
1874          }
1875          this.intersectionObserver?.observe(child);
1876        });
1877      } else {
1878        it.childrenList.forEach((child) => {
1879          if (child.hasAttribute('scene') && !child.collect) {
1880            child.rowHidden = true;
1881            this.intersectionObserver?.unobserve(child);
1882          }
1883          if (child.folder) {
1884            child.removeEventListener('expansion-change', this.extracted(child));
1885          }
1886        });
1887        this.linkNodes.map((value) => {
1888          if ('task' === value[0].business && value[0].rowEL.parentRowEl?.rowId === it.rowId) {
1889            value[0].hidden = true;
1890            value[1].hidden = true;
1891            this.clickEmptyArea();
1892          }
1893        });
1894      }
1895      if (!this.collapseAll) {
1896        this.refreshCanvas(false);
1897      }
1898    };
1899  }
1900
1901  displayTip(row: TraceRow<any>, struct: any, html: string) {
1902    let x = row.hoverX + 248;
1903    let y = row.getBoundingClientRect().top - this.getBoundingClientRect().top;
1904    if ((struct === undefined || struct === null) && this.tipEL) {
1905      this.tipEL.style.display = 'none';
1906      return;
1907    }
1908    if (this.tipEL) {
1909      this.tipEL.innerHTML = html;
1910      if (row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER || row.rowType === TraceRow.ROW_TYPE_PERF_CALLCHART) {
1911        this.tipEL.style.maxWidth = row.clientWidth / 3 + 'px';
1912        this.tipEL.style.wordBreak = ' break-all';
1913        this.tipEL.style.height = 'unset';
1914        this.tipEL.style.display = 'block';
1915        y = y + struct.depth * 20;
1916      } else {
1917        this.tipEL.style.display = 'flex';
1918        this.tipEL.style.height = row.style.height;
1919      }
1920      if (x + this.tipEL.clientWidth > (this.canvasPanel!.clientWidth ?? 0)) {
1921        this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px) translateY(${y}px)`;
1922      } else {
1923        this.tipEL.style.transform = `translateX(${x}px) translateY(${y}px)`;
1924      }
1925    }
1926  }
1927
1928  queryCPUWakeUpList(data: WakeupBean): void {
1929    TabPaneCurrentSelection.queryCPUWakeUpListFromBean(data).then((a: any) => {
1930      if (a === null) {
1931        window.publish(window.SmartEvent.UI.WakeupList, SpSystemTrace.wakeupList);
1932        return null;
1933      }
1934      SpSystemTrace.wakeupList.push(a);
1935      this.queryCPUWakeUpList(a);
1936    });
1937  }
1938
1939  wakeupListNull() {
1940    SpSystemTrace.wakeupList = [];
1941    return this;
1942  }
1943
1944  initPointToEvent(): void {
1945    spSystemTraceInitPointToEvent(this);
1946  }
1947
1948  initHtml(): string {
1949    return SpSystemTraceHtml;
1950  }
1951}
1952