• 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, threadPool2 } 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  prioClickHandlerFun,
46  drawThreadCurve,
47} from '../database/ui-worker/ProcedureWorkerCommon';
48import { SpChartManager } from './chart/SpChartManager';
49import { CpuStruct, WakeupBean } from '../database/ui-worker/cpu/ProcedureWorkerCPU';
50import { ProcessStruct } from '../database/ui-worker/ProcedureWorkerProcess';
51import { CpuFreqStruct } from '../database/ui-worker/ProcedureWorkerFreq';
52import { CpuFreqLimitsStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits';
53import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread';
54import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc';
55import { CpuStateStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuState';
56import { HiPerfCpuStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfCPU2';
57import { HiPerfProcessStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfProcess2';
58import { HiPerfThreadStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfThread2';
59import { HiPerfEventStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfEvent';
60import { HiPerfReportStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfReport';
61import { FpsStruct } from '../database/ui-worker/ProcedureWorkerFPS';
62import { CpuAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerCpuAbility';
63import { DiskAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerDiskIoAbility';
64import { MemoryAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerMemoryAbility';
65import { NetworkAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerNetworkAbility';
66import { ClockStruct } from '../database/ui-worker/ProcedureWorkerClock';
67import { DmaFenceStruct } from '../database/ui-worker/ProcedureWorkerDmaFence';
68import { Utils } from './trace/base/Utils';
69import { IrqStruct } from '../database/ui-worker/ProcedureWorkerIrq';
70import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank';
71import { TabPaneCurrent } from './trace/sheet/TabPaneCurrent';
72import { HeapStruct } from '../database/ui-worker/ProcedureWorkerHeap';
73import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil';
74import { HeapSnapshotStruct } from '../database/ui-worker/ProcedureWorkerHeapSnapshot';
75import { HeapDataInterface } from '../../js-heap/HeapDataInterface';
76import { LitTabs } from '../../base-ui/tabs/lit-tabs';
77import { TraceRowConfig } from './trace/base/TraceRowConfig';
78import { TabPaneCurrentSelection } from './trace/sheet/TabPaneCurrentSelection';
79import { SpChartList } from './trace/SpChartList';
80import './trace/SpChartList';
81import { AppStartupStruct } from '../database/ui-worker/ProcedureWorkerAppStartup';
82import { AllAppStartupStruct } from '../database/ui-worker/ProcedureWorkerAllAppStartup';
83import { SoStruct } from '../database/ui-worker/ProcedureWorkerSoInit';
84import { FrameDynamicStruct } from '../database/ui-worker/ProcedureWorkerFrameDynamic';
85import { FrameAnimationStruct } from '../database/ui-worker/ProcedureWorkerFrameAnimation';
86import { FrameSpacingStruct } from '../database/ui-worker/ProcedureWorkerFrameSpacing';
87import { JsCpuProfilerStruct } from '../database/ui-worker/ProcedureWorkerCpuProfiler';
88import { FileInfo } from '../../js-heap/model/UiStruct';
89import { SnapshotStruct } from '../database/ui-worker/ProcedureWorkerSnapshot';
90import { TabPaneFrequencySample } from './trace/sheet/cpu/TabPaneFrequencySample';
91import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample';
92import { TabPaneFlag } from './trace/timer-shaft/TabPaneFlag';
93import { LitTabpane } from '../../base-ui/tabs/lit-tabpane';
94import { HiPerfCallChartStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfCallChart';
95import { InitAnalysis } from '../database/logic-worker/ProcedureLogicWorkerCommon';
96import { searchCpuDataSender } from '../database/data-trafic/CpuDataSender';
97import { resetVSync } from './chart/VSync';
98import { QueryEnum } from '../database/data-trafic/utils/QueryEnum';
99import { SpSystemTraceHtml } from './SpSystemTrace.html';
100import { querySceneSearchFunc, querySearchFunc } from '../database/sql/Func.sql';
101import { queryCpuKeyPathData } from '../database/sql/Cpu.sql';
102import { LtpoStruct } from '../database/ui-worker/ProcedureWorkerLTPO';
103import { HitchTimeStruct } from '../database/ui-worker/ProcedureWorkerHitchTime';
104import { ProcessMemStruct } from '../database/ui-worker/ProcedureWorkerMem';
105import {
106  spSystemTraceInit,
107  spSystemTraceInitElement,
108  spSystemTraceInitPointToEvent,
109  spSystemTraceParentRowSticky,
110  spSystemTraceShowStruct,
111} from './SpSystemTrace.init';
112import {
113  spSystemTraceDrawDistributedLine,
114  spSystemTraceDrawFuncLine,
115  spSystemTraceDrawJankLine,
116  spSystemTraceDrawTaskPollLine,
117  spSystemTraceDrawThreadLine,
118} from './SpSystemTrace.line';
119import spSystemTraceOnClickHandler, {
120  spSystemTraceDocumentOnClick,
121  spSystemTraceDocumentOnKeyDown,
122  spSystemTraceDocumentOnKeyPress,
123  spSystemTraceDocumentOnKeyUp,
124  spSystemTraceDocumentOnMouseDown,
125  spSystemTraceDocumentOnMouseMove,
126  spSystemTraceDocumentOnMouseOut,
127  spSystemTraceDocumentOnMouseUp,
128} from './SpSystemTrace.event';
129import { SampleStruct } from '../database/ui-worker/ProcedureWorkerBpftrace';
130import { readTraceFileBuffer } from '../SpApplicationPublicFunc';
131import { PerfToolStruct } from '../database/ui-worker/ProcedureWorkerPerfTool';
132import { BaseStruct } from '../bean/BaseStruct';
133import { GpuCounterStruct } from '../database/ui-worker/ProcedureWorkerGpuCounter';
134import { SpProcessChart } from './chart/SpProcessChart';
135import { HangStruct } from '../database/ui-worker/ProcedureWorkerHang';
136
137function dpr(): number {
138  return window.devicePixelRatio || 1;
139}
140
141export class CurrentSlicesTime {
142  startTime: number | undefined;
143  endTime: number | undefined;
144}
145
146type HTMLDivElementAlias = HTMLDivElement | undefined | null;
147type FlagAlias = Flag | undefined | null;
148type SlicesTimeAlias = SlicesTime | undefined | null;
149
150@element('sp-system-trace')
151export class SpSystemTrace extends BaseElement {
152  mouseCurrentPosition = 0;
153  static isKeyUp: boolean = true;
154  offsetMouse = 0;
155  static isMouseLeftDown = false;
156  static scrollViewWidth = 0;
157  static isCanvasOffScreen = true;
158  static DATA_DICT: Map<number, string> = new Map<number, string>();
159  static DATA_TASK_POOL_CALLSTACK: Map<number, { id: number; ts: number; dur: number; name: string }> = new Map<
160    number,
161    { id: number; ts: number; dur: number; name: string }
162  >();
163  static SDK_CONFIG_MAP: unknown;
164  static sliceRangeMark: unknown;
165  static wakeupList: Array<WakeupBean> = [];
166  static keyPathList: Array<CpuStruct> = [];
167  static keyboardFlar: Boolean = true;
168  static jsProfilerMap: Map<number, unknown> = new Map<number, unknown>();
169  times: Set<number> = new Set<number>();
170  currentSlicesTime: CurrentSlicesTime = new CurrentSlicesTime();
171  intersectionObserver: IntersectionObserver | undefined;
172  tipEL: HTMLDivElementAlias;
173  rowsEL: HTMLDivElementAlias;
174  rowsPaneEL: HTMLDivElementAlias;
175  stateRowsId: Array<object> = [];
176  spacerEL: HTMLDivElementAlias; // @ts-ignore
177  visibleRows: Array<TraceRow<unknown>> = []; // @ts-ignore
178  invisibleRows: Array<TraceRow<unknown>> = []; // @ts-ignore
179  collectRows: Array<TraceRow<unknown>> = []; // @ts-ignore
180  currentRow: TraceRow<unknown> | undefined | null;
181  keyboardEnable = true;
182  mouseEventEnable = true;
183  currentRowType = ''; /*保存当前鼠标所在行的类型*/
184  observerScrollHeightEnable: boolean = false;
185  observerScrollHeightCallback: Function | undefined;
186  favoriteChartListEL: SpChartList | undefined | null;
187  // @ts-ignore
188  observer = new ResizeObserver((entries) => {
189    if (this.observerScrollHeightEnable && this.observerScrollHeightCallback) {
190      this.observerScrollHeightCallback();
191    }
192  });
193  static btnTimer: unknown = null;
194  isMousePointInSheet = false;
195  hoverFlag: FlagAlias;
196  selectFlag: FlagAlias;
197  slicestime: SlicesTimeAlias;
198  public timerShaftEL: TimerShaftElement | null | undefined;
199  public traceSheetEL: TraceSheet | undefined | null;
200  public rangeSelect!: RangeSelect;
201  chartManager: SpChartManager | undefined | null;
202  loadTraceCompleted: boolean = false; // @ts-ignore
203  rangeTraceRow: Array<TraceRow<unknown>> | undefined = [];
204  canvasFavoritePanelCtx: CanvasRenderingContext2D | null | undefined;
205  canvasPanel: HTMLCanvasElement | null | undefined; //绘制取消收藏后泳道图
206  canvasPanelCtx: CanvasRenderingContext2D | undefined | null;
207  linkNodes: PairPoint[][] = [];
208  public currentClickRow: HTMLDivElement | undefined | null;
209  private litTabs: LitTabs | undefined | null;
210  eventMap: unknown = {};
211  isSelectClick: boolean = false;
212  selectionParam: SelectionParam | undefined;
213  snapshotFiles: FileInfo | null | undefined;
214  tabCpuFreq: TabPaneFrequencySample | undefined | null;
215  tabCpuState: TabPaneCounterSample | undefined | null;
216  collapseAll: boolean = false;
217  currentCollectGroup: string = '1';
218  private _list: Array<SlicesTime> = [];
219  static isHiddenMenu: boolean = false; // @ts-ignore
220  expandRowList: Array<TraceRow<unknown>> = [];
221  _slicesList: Array<SlicesTime> = [];
222  _flagList: Array<unknown> = [];
223  static currentStartTime: number = 0;
224  static retargetIndex: number = 0;
225  prevScrollY: number = 0;
226  focusTarget: string = '';
227
228  set snapshotFile(data: FileInfo) {
229    this.snapshotFiles = data;
230  }
231
232  set slicesList(list: Array<SlicesTime>) {
233    this._slicesList = list;
234  }
235
236  set flagList(list: Array<unknown>) {
237    this._flagList = list;
238  }
239
240  //节流处理
241  throttle(fn: Function, t: number, ev?: unknown): Function {
242    let timerId: unknown = null;
243    return (): void => {
244      if (!timerId) {
245        timerId = setTimeout(function (): void {
246          if (ev) {
247            fn(ev);
248          } else {
249            fn();
250          }
251          timerId = null;
252        }, t); // @ts-ignore
253        this.times.add(timerId);
254      }
255    };
256  }
257
258  // 防抖处理
259  debounce(fn: Function, ms: number, ev?: unknown): Function {
260    let timerId: undefined | number;
261    return (): void => {
262      if (timerId) {
263        window.clearTimeout(timerId);
264      } else {
265        timerId = window.setTimeout((): void => {
266          if (ev) {
267            fn(ev);
268          } else {
269            fn();
270          }
271          timerId = undefined;
272        }, ms);
273        this.times.add(timerId);
274      }
275    };
276  }
277
278  addPointPair(startPoint: PairPoint, endPoint: PairPoint, lineType?: string): void {
279    if (startPoint !== null && startPoint.rowEL !== null && endPoint !== null && endPoint.rowEL !== null) {
280      if (startPoint.rowEL.collect) {
281        if (this.timerShaftEL?._checkExpand) {
282          startPoint.rowEL.translateY =
283            startPoint.rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!;
284        } else {
285          startPoint.rowEL.translateY = startPoint.rowEL.getBoundingClientRect().top - 195;
286        }
287      } else {
288        startPoint.rowEL.translateY = startPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
289      }
290      if (endPoint.rowEL.collect) {
291        endPoint.rowEL.translateY = endPoint.rowEL.getBoundingClientRect().top - 195;
292      } else {
293        endPoint.rowEL.translateY = endPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
294      }
295      startPoint.y = startPoint.rowEL!.translateY! + startPoint.offsetY;
296      endPoint.y = endPoint.rowEL!.translateY! + endPoint.offsetY;
297      startPoint.backrowEL = startPoint.rowEL;
298      endPoint.backrowEL = endPoint.rowEL;
299      //判断是否是分布式连线,分布式连线需有rangeTime
300      if (!lineType) {
301        this.linkNodes.push([startPoint, endPoint]);
302      } else {
303        if (startPoint.rangeTime) {
304          this.linkNodes.push([startPoint, endPoint]);
305        }
306      }
307      this.refreshCanvas(true);
308    }
309  }
310
311  clearPointPair(): void {
312    this.linkNodes.length = 0;
313  }
314
315  removeLinkLinesByBusinessType(...businessTypes: string[]): void {
316    this.linkNodes = this.linkNodes.filter((pointPair) => {
317      if (businessTypes.indexOf('distributed') >= 0) {
318        FuncStruct.selectLineFuncStruct = [];
319      }
320      return businessTypes.indexOf(pointPair[0].business) <= -1;
321    });
322  }
323
324  hiddenLinkLinesByBusinessType(...businessTypes: string[]): void {
325    this.linkNodes.map((value) => {
326      if (businessTypes.indexOf(value[0].business) !== -1) {
327        value[0].hidden = true;
328        value[1].hidden = true;
329      }
330    });
331  }
332
333  showLinkLinesByBusinessType(...businessTypes: string[]): void {
334    this.linkNodes.map((value) => {
335      if (businessTypes.indexOf(value[0].business) !== -1) {
336        value[0].hidden = false;
337        value[1].hidden = false;
338      }
339    });
340  }
341
342  initElements(): void {
343    spSystemTraceInitElement(this);
344  }
345
346  // 清除上一次点击调用栈产生的三角旗子
347  clearTriangle(flagList: Array<Flag>): void {
348    this.timerShaftEL!.sportRuler!.times = [];
349    for (let i = 0; i < flagList.length; i++) {
350      if (flagList[i].type === 'triangle') {
351        flagList.splice(i, 1);
352        this.timerShaftELFlagChange(this.hoverFlag, null);
353        i--;
354      }
355    }
356  }
357
358  pushPidToSelection(selection: SelectionParam, id: string): void {
359    let pid = parseInt(id);
360    if (!isNaN(pid)) {
361      if (!selection.processIds.includes(pid)) {
362        selection.processIds.push(pid);
363      }
364    }
365  }
366  // @ts-ignore
367  getCollectRows(condition: (row: TraceRow<unknown>) => boolean): Array<TraceRow<unknown>> {
368    return this.favoriteChartListEL!.getCollectRows(condition);
369  }
370  // @ts-ignore
371  createPointEvent(it: TraceRow<unknown>): unknown {
372    // @ts-ignore
373    let event = this.eventMap[`${it.rowType}`];
374    if (event) {
375      return event;
376    } else {
377      if (it.rowType === TraceRow.ROW_TYPE_HEAP) {
378        event = it.name;
379      } else if (it.rowType === TraceRow.ROW_TYPE_HIPERF_CPU) {
380        event = 'HiPerf Cpu';
381        if (it.rowId === 'HiPerf-cpu-merge') {
382          event = 'HiPerf';
383        }
384      } else if (it.rowType === TraceRow.ROW_TYPE_FILE_SYSTEM) {
385        event = this.handleFileSystemType(it, event);
386      } else if (it.rowType === TraceRow.ROW_TYPE_STATE_ENERGY) {
387        event = it.name;
388      } else if (it.rowType === TraceRow.ROW_TYPE_VM_TRACKER) {
389        if (it.rowParentId === '') {
390          event = 'VM Tracker';
391        } else {
392          event = it.name;
393        }
394      } else if (it.rowType === TraceRow.ROW_TYPE_JANK) {
395        if (it.rowId === 'frameTime' || it.rowParentId === 'frameTime') {
396          event = 'FrameTimeLine';
397        } else if (it.hasAttribute('frame_type')) {
398          event = `${it.getAttribute('frame_type')}`;
399        }
400      } else if (it.rowType === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) {
401        event = 'DeliverInputEvent';
402        if (it.rowParentId === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) {
403          event = 'DeliverInputEvent Func';
404        }
405      } else if (it.rowType === TraceRow.ROW_TYPE_TOUCH_EVENT_DISPATCH) {
406        event = 'TouchEventDispatch';
407        if (it.rowParentId === TraceRow.ROW_TYPE_TOUCH_EVENT_DISPATCH) {
408          event = 'TouchEventDispatch Func';
409        }
410      } else {
411        event = it.name;
412      }
413      return event;
414    }
415  }
416  // @ts-ignore
417  private handleFileSystemType(it: TraceRow<unknown>, event: unknown): void {
418    if (it.rowId === 'FileSystemLogicalWrite') {
419      event = 'FileSystem Logical Write';
420    } else if (it.rowId === 'FileSystemLogicalRead') {
421      event = 'FileSystem Logical Read';
422    } else if (it.rowId === 'FileSystemVirtualMemory') {
423      event = 'Page Fault Trace';
424    } else if (it.rowId!.startsWith('FileSystemDiskIOLatency')) {
425      event = 'Disk I/O Latency';
426      if (it.rowId!.startsWith('FileSystemDiskIOLatency-')) {
427        event = 'Bio Process';
428      }
429    } // @ts-ignore
430    return event;
431  }
432
433  refreshFavoriteCanvas(): void {
434    this.favoriteChartListEL!.refreshFavoriteCanvas();
435  }
436  // @ts-ignore
437  expansionAllParentRow(currentRow: TraceRow<unknown>): void {
438    // @ts-ignore
439    let parentRow = this.rowsEL!.querySelector<TraceRow<unknown>>(
440      `trace-row[row-id='${currentRow.rowParentId}'][folder][scene]`
441    );
442    if (parentRow) {
443      parentRow.expansion = true; // @ts-ignore
444      if (this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${parentRow.rowParentId}'][folder]`)) {
445        this.expansionAllParentRow(parentRow);
446      }
447    }
448  }
449
450  canvasPanelConfig(): void {
451    this.canvasPanel!.style.left = `${this.timerShaftEL!.canvas!.offsetLeft!}px`;
452    this.canvasPanel!.width = this.canvasPanel!.offsetWidth * dpr();
453    this.canvasPanel!.height = this.canvasPanel!.offsetHeight * dpr();
454    this.canvasPanelCtx!.scale(dpr(), dpr());
455  }
456
457  getScrollWidth(): number {
458    let overflowDiv = document.createElement('div');
459    overflowDiv.style.cssText = 'position:absolute; top:-2000px;width:200px; height:200px; overflow:hidden;';
460    let totalScrollDiv = document.body.appendChild(overflowDiv).clientWidth;
461    overflowDiv.style.overflowY = 'scroll';
462    let scrollDiv = overflowDiv.clientWidth;
463    document.body.removeChild(overflowDiv);
464    return totalScrollDiv - scrollDiv;
465  }
466
467  getShowTab(): Array<string> {
468    let tabpane = this.traceSheetEL!.shadowRoot!.querySelectorAll('lit-tabpane') as NodeListOf<LitTabpane>;
469    let showTab: Array<string> = [];
470    for (let pane of tabpane) {
471      if (pane.getAttribute('hidden') === 'false') {
472        showTab.push(pane.getAttribute('id') || '');
473      }
474    }
475    return showTab;
476  }
477
478  timerShaftELFlagClickHandler = (flag: FlagAlias): void => {
479    if (flag) {
480      setTimeout(() => {
481        if (TraceRow.rangeSelectObject) {
482          let showTab = this.getShowTab();
483          this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag', ...showTab).setCurrentFlag(flag);
484        } else {
485          this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag').setCurrentFlag(flag);
486        }
487      }, 100);
488    }
489  };
490
491  timerShaftELFlagChange = (hoverFlag: FlagAlias, selectFlag: FlagAlias): void => {
492    this.hoverFlag = hoverFlag;
493    this.selectFlag = selectFlag;
494    this.refreshCanvas(true, 'flagChange');
495  };
496
497  timerShaftELRangeClick = (sliceTime: SlicesTimeAlias): void => {
498    if (sliceTime) {
499      setTimeout(() => {
500        if (TraceRow.rangeSelectObject) {
501          let showTab = this.getShowTab();
502          this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current', ...showTab).setCurrentSlicesTime(sliceTime);
503        } else {
504          this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(sliceTime);
505        }
506      }, 0);
507    }
508  };
509
510  timerShaftELRangeChange = (e: unknown): void => {
511    // @ts-ignore
512    TraceRow.range = e;
513    if (TraceRow.rangeSelectObject) {
514      TraceRow.rangeSelectObject!.startX = Math.floor(
515        ns2x(
516          TraceRow.rangeSelectObject!.startNS!,
517          TraceRow.range?.startNS!,
518          TraceRow.range?.endNS!,
519          TraceRow.range?.totalNS!,
520          this.timerShaftEL!.sportRuler!.frame
521        )
522      );
523      TraceRow.rangeSelectObject!.endX = Math.floor(
524        ns2x(
525          TraceRow.rangeSelectObject!.endNS!,
526          TraceRow.range?.startNS!,
527          TraceRow.range?.endNS!,
528          TraceRow.range?.totalNS!,
529          this.timerShaftEL!.sportRuler!.frame
530        )
531      );
532    }
533    //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知
534    this.linkNodes.forEach((it) => {
535      it[0].x = ns2xByTimeShaft(it[0].ns, this.timerShaftEL!);
536      it[1].x = ns2xByTimeShaft(it[1].ns, this.timerShaftEL!);
537    });
538    this.invisibleRows.forEach((it) => (it.needRefresh = true));
539    this.visibleRows.forEach((it) => (it.needRefresh = true));
540    this.refreshCanvas(false, 'rangeChange');
541  };
542  top: number = 0;
543  handler: number = -1;
544  rowsElOnScroll = (e: unknown): void => {
545    // @ts-ignore
546    const currentScrollY = e.target.scrollTop;
547    const deltaY = currentScrollY - this.prevScrollY;
548    this.linkNodes.forEach((itln) => {
549      if (itln[0].rowEL.collect) {
550        if (this.timerShaftEL?._checkExpand) {
551          itln[0].rowEL.translateY =
552            itln[0].rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!;
553        } else {
554          itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195;
555        }
556      } else {
557        itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
558      }
559      if (itln[1].rowEL.collect) {
560        if (this.timerShaftEL?._checkExpand) {
561          itln[1].rowEL.translateY =
562            itln[1].rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!;
563        } else {
564          itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195;
565        }
566      } else {
567        itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
568      }
569      itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY;
570      itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY;
571    });
572    this.hoverStructNull();
573    if (this.scrollTimer) {
574      // @ts-ignore
575      clearTimeout(this.scrollTimer);
576    }
577    this.scrollTimer = setTimeout(() => {
578      TraceRow.range!.refresh = true;
579      requestAnimationFrame(() => this.refreshCanvas(false));
580    }, 200);
581    spSystemTraceParentRowSticky(this, deltaY);
582    this.prevScrollY = currentScrollY;
583  };
584
585  private scrollTimer: unknown;
586
587  favoriteRowsElOnScroll = (e: unknown): void => {
588    this.rowsElOnScroll(e);
589  };
590
591  offset = 147;
592
593  getRowsContentHeight(): number {
594    // @ts-ignore
595    return [...this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row:not([sleeping])')]
596      .map((it) => it.clientHeight)
597      .reduce((acr, cur) => acr + cur, 0);
598  }
599
600  // refresh main canvas and favorite canvas
601  refreshCanvas(cache: boolean, from?: string): void {
602    if (this.visibleRows.length === 0) {
603      return;
604    }
605    //clear main canvas
606    this.canvasPanelCtx!.clearRect(0, 0, this.canvasPanel!.offsetWidth, this.canvasPanel!.offsetHeight);
607    this.favoriteChartListEL!.clearRect();
608    //draw lines for main canvas
609    let rowsContentHeight = this.getRowsContentHeight();
610    let canvasHeight =
611      rowsContentHeight > this.canvasPanel!.clientHeight ? this.canvasPanel!.clientHeight : rowsContentHeight;
612    drawLines(this.canvasPanelCtx!, TraceRow.range?.xs || [], canvasHeight, this.timerShaftEL!.lineColor());
613    //draw lines for favorite canvas
614    this.favoriteChartListEL?.drawLines(TraceRow.range?.xs, this.timerShaftEL!.lineColor()); // chart list
615
616    //canvas translate
617    this.canvasPanel!.style.transform = `translateY(${this.rowsPaneEL!.scrollTop}px)`;
618    //draw trace row
619    this.visibleRows.forEach((v, i) => {
620      if (v.collect) {
621        v.translateY =
622          v.getBoundingClientRect().top -
623          this.timerShaftEL?.clientHeight! -
624          this.parentElement!.previousElementSibling!.clientHeight -
625          1;
626      } else {
627        v.translateY = v.offsetTop - this.rowsPaneEL!.scrollTop;
628      }
629      v.draw(cache);
630    });
631    this.drawAllLines();
632  }
633
634  drawWakeUpLine(): void {
635    //draw wakeup for main canvas
636    drawWakeUp(
637      this.canvasPanelCtx,
638      CpuStruct.wakeupBean,
639      TraceRow.range!.startNS,
640      TraceRow.range!.endNS,
641      TraceRow.range!.totalNS,
642      {
643        x: 0,
644        y: 0,
645        width: TraceRow.FRAME_WIDTH,
646        height: this.canvasPanel!.clientHeight!,
647      } as Rect
648    );
649    this.favoriteChartListEL?.drawWakeUp();
650    // draw wakeuplist for main canvas
651    for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) {
652      if (i + 1 === SpSystemTrace.wakeupList.length) {
653        return;
654      }
655      drawWakeUpList(
656        this.canvasPanelCtx,
657        SpSystemTrace.wakeupList[i + 1],
658        TraceRow.range!.startNS,
659        TraceRow.range!.endNS,
660        TraceRow.range!.totalNS,
661        {
662          x: 0,
663          y: 0,
664          width: this.timerShaftEL!.canvas!.clientWidth,
665          height: this.canvasPanel!.clientHeight!,
666        } as Rect
667      );
668      this.favoriteChartListEL?.drawWakeUpList(SpSystemTrace.wakeupList[i + 1]);
669    }
670  }
671
672  drawAllLines(): void {
673    // draw flag line segment for canvas
674    drawFlagLineSegment(
675      this.canvasPanelCtx,
676      this.hoverFlag,
677      this.selectFlag,
678      {
679        x: 0,
680        y: 0,
681        width: this.timerShaftEL?.canvas?.clientWidth,
682        height: this.canvasPanel?.clientHeight,
683      } as Rect,
684      this.timerShaftEL!
685    );
686    this.favoriteChartListEL?.drawFlagLineSegment(this.hoverFlag, this.selectFlag, this.timerShaftEL!);
687    this.drawWakeUpLine();
688    //draw system logs line segment for canvas
689    drawLogsLineSegment(
690      this.canvasPanelCtx,
691      this.traceSheetEL?.systemLogFlag,
692      {
693        x: 0,
694        y: 0,
695        width: this.timerShaftEL?.canvas?.clientWidth,
696        height: this.canvasPanel?.clientHeight,
697      },
698      this.timerShaftEL!
699    );
700    this.favoriteChartListEL?.drawLogsLineSegment(this.traceSheetEL!.systemLogFlag, this.timerShaftEL!);
701
702    // Draw the connection curve
703    if (this.linkNodes && this.linkNodes.length > 0) {
704      drawLinkLines(
705        this.canvasPanelCtx!,
706        this.linkNodes,
707        this.timerShaftEL!,
708        false,
709        this.favoriteChartListEL!.clientHeight
710      );
711      this.favoriteChartListEL?.drawLinkLines(
712        this.linkNodes,
713        this.timerShaftEL!,
714        true,
715        this.favoriteChartListEL!.clientHeight
716      );
717    }
718    // draw prio curve
719    if (
720      ThreadStruct.isClickPrio &&
721      this.currentRow!.parentRowEl!.expansion &&
722      ThreadStruct.selectThreadStruct &&
723      ThreadStruct.contrast(ThreadStruct.selectThreadStruct, this.currentRow!.rowParentId, this.currentRow!.rowId)
724    ) {
725      let context: CanvasRenderingContext2D;
726      if (this.currentRow!.currentContext) {
727        context = this.currentRow!.currentContext;
728      } else {
729        context = this.currentRow!.collect ? this.canvasFavoritePanelCtx! : this.canvasPanelCtx!;
730      }
731      this.drawPrioCurve(context, this.currentRow!);
732    }
733  }
734
735  // draw prio curve
736  // @ts-ignore
737  drawPrioCurve(context: unknown, row: TraceRow<unknown>): void {
738    let curveDrawList: unknown = [];
739    let oldVal: number = -1;
740    // @ts-ignore
741    let threadFilter = row.dataListCache.filter((it: unknown) => it.state === 'Running'); //筛选状态是Running的数据
742    //计算每个点的坐标
743    // @ts-ignore
744    prioClickHandlerFun(ThreadStruct.prioCount, row, threadFilter, curveDrawList, oldVal);
745    //绘制曲线透明度设置1,根据计算的曲线坐标开始画图
746    // @ts-ignore
747    context.globalAlpha = 1;
748    // @ts-ignore
749    context.beginPath();
750    let x0;
751    let y0;
752    // @ts-ignore
753    if (curveDrawList[0] && curveDrawList[0].frame) {
754      // @ts-ignore
755      x0 = curveDrawList[0].frame.x;
756      // @ts-ignore
757      y0 = curveDrawList[0].curveFloatY;
758    }
759    // @ts-ignore
760    context!.moveTo(x0!, y0!);
761    // @ts-ignore
762    if (SpSystemTrace.isKeyUp || curveDrawList.length < 90) {
763      // @ts-ignore
764      for (let i = 0; i < curveDrawList.length - 1; i++) {
765        // @ts-ignore
766        let re = curveDrawList[i];
767        // @ts-ignore
768        let nextRe = curveDrawList[i + 1];
769        // @ts-ignore
770        drawThreadCurve(context, re, nextRe);
771      }
772      // @ts-ignore
773      context.closePath();
774      // @ts-ignore
775    } else if (!SpSystemTrace.isKeyUp && curveDrawList.length >= 90) {
776      let x;
777      let y;
778      // @ts-ignore
779      if (curveDrawList[curveDrawList.length - 1] && curveDrawList[curveDrawList.length - 1].frame) {
780        // @ts-ignore
781        x = curveDrawList[curveDrawList.length - 1].frame.x;
782        // @ts-ignore
783        y = curveDrawList[curveDrawList.length - 1].curveFloatY;
784      }
785      // @ts-ignore
786      context.lineWidth = 1;
787      // @ts-ignore
788      context.strokeStyle = '#ffc90e';
789      // @ts-ignore
790      context.lineCap = 'round';
791      // @ts-ignore
792      context.lineTo(x, y);
793      // @ts-ignore
794      context.stroke();
795    }
796  }
797
798  documentOnMouseDown = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseDown(this, ev);
799
800  onContextMenuHandler = (e: Event): void => {
801    setTimeout(() => {
802      for (let key of this.keyPressMap.keys()) {
803        if (this.keyPressMap.get(key)) {
804          this.timerShaftEL?.stopWASD({ key: key });
805          this.keyPressMap.set(key, false);
806        }
807      }
808    }, 100);
809  };
810
811  documentOnMouseUp = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseUp(this, ev);
812
813  cancelDrag(): void {
814    this.rangeSelect.drag = false;
815    this.rangeSelect.isMouseDown = false;
816    TraceRow.rangeSelectObject = {
817      startX: 0,
818      endX: 0,
819      startNS: 0,
820      endNS: 0,
821    };
822  }
823
824  documentOnMouseOut = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseOut(this, ev);
825
826  keyPressMap: Map<string, boolean> = new Map([
827    ['w', false],
828    ['s', false],
829    ['a', false],
830    ['d', false],
831    ['f', false],
832  ]);
833
834  documentOnKeyDown = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyDown(this, ev);
835
836  documentOnKeyPress = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyPress(this, ev);
837
838  verticalScrollToRow(): void {
839    if (this.currentRow) {
840      //@ts-ignore
841      this.currentRow.scrollIntoViewIfNeeded();
842    }
843  }
844
845  setCurrentSlicesTime(): void {
846    if (CpuStruct.selectCpuStruct) {
847      this.currentSlicesTime.startTime = CpuStruct.selectCpuStruct.startTime;
848      this.currentSlicesTime.endTime = CpuStruct.selectCpuStruct.startTime! + CpuStruct.selectCpuStruct.dur!;
849    } else if (ThreadStruct.selectThreadStruct) {
850      this.currentSlicesTime.startTime = ThreadStruct.selectThreadStruct.startTime;
851      this.currentSlicesTime.endTime =
852        ThreadStruct.selectThreadStruct.startTime! + ThreadStruct.selectThreadStruct.dur!;
853    } else if (FuncStruct.selectFuncStruct) {
854      this.currentSlicesTime.startTime = FuncStruct.selectFuncStruct.startTs;
855      this.currentSlicesTime.endTime = FuncStruct.selectFuncStruct.startTs! + FuncStruct.selectFuncStruct.dur!;
856    } else if (IrqStruct.selectIrqStruct) {
857      this.currentSlicesTime.startTime = IrqStruct.selectIrqStruct.startNS;
858      this.currentSlicesTime.endTime = IrqStruct.selectIrqStruct.startNS! + IrqStruct.selectIrqStruct.dur!;
859    } else if (TraceRow.rangeSelectObject) {
860      this.currentRow = undefined;
861      if (TraceRow.rangeSelectObject.startNS && TraceRow.rangeSelectObject.endNS) {
862        this.currentSlicesTime.startTime = TraceRow.rangeSelectObject.startNS;
863        this.currentSlicesTime.endTime = TraceRow.rangeSelectObject.endNS;
864      }
865    } else if (JankStruct.selectJankStruct) {
866      this.currentSlicesTime.startTime = JankStruct.selectJankStruct.ts;
867      this.currentSlicesTime.endTime = JankStruct.selectJankStruct.ts! + JankStruct.selectJankStruct.dur!;
868    } else if (SampleStruct.selectSampleStruct) {
869      if (SampleStruct.selectSampleStruct.begin && SampleStruct.selectSampleStruct.end) {
870        this.currentSlicesTime.startTime =
871          SampleStruct.selectSampleStruct.begin - SampleStruct.selectSampleStruct.startTs!;
872        this.currentSlicesTime.endTime = SampleStruct.selectSampleStruct.end - SampleStruct.selectSampleStruct.startTs!;
873      }
874    } else if (GpuCounterStruct.selectGpuCounterStruct) {
875      this.currentSlicesTime.startTime =
876        GpuCounterStruct.selectGpuCounterStruct.startNS! - GpuCounterStruct.selectGpuCounterStruct.startTime!;
877      this.currentSlicesTime.endTime =
878        GpuCounterStruct.selectGpuCounterStruct.startNS! +
879        GpuCounterStruct.selectGpuCounterStruct.dur! -
880        GpuCounterStruct.selectGpuCounterStruct.startTime!;
881    } else if (AppStartupStruct.selectStartupStruct) {
882      this.currentSlicesTime.startTime = AppStartupStruct.selectStartupStruct.startTs;
883      this.currentSlicesTime.endTime = AppStartupStruct.selectStartupStruct.startTs! + AppStartupStruct.selectStartupStruct.dur!;
884    } else if (AllAppStartupStruct.selectStartupStruct) {
885      this.currentSlicesTime.startTime = AllAppStartupStruct.selectStartupStruct.startTs;
886      this.currentSlicesTime.endTime = AllAppStartupStruct.selectStartupStruct.startTs! + AllAppStartupStruct.selectStartupStruct.dur!;
887    } else if (PerfToolStruct.selectPerfToolStruct) {
888      this.currentSlicesTime.startTime = PerfToolStruct.selectPerfToolStruct.startTs;
889      this.currentSlicesTime.endTime = PerfToolStruct.selectPerfToolStruct.startTs! + PerfToolStruct.selectPerfToolStruct.dur!;
890    } else if (DmaFenceStruct.selectDmaFenceStruct) {
891      if (DmaFenceStruct.selectDmaFenceStruct.startTime && DmaFenceStruct.selectDmaFenceStruct.dur) {
892        this.currentSlicesTime.startTime = DmaFenceStruct.selectDmaFenceStruct.startTime;
893        this.currentSlicesTime.endTime = DmaFenceStruct.selectDmaFenceStruct.startTime + DmaFenceStruct.selectDmaFenceStruct.dur;
894      }
895    } else {
896      this.currentSlicesTime.startTime = 0;
897      this.currentSlicesTime.endTime = 0;
898    }
899  }
900
901  public setSLiceMark = (shiftKey: boolean): SlicesTime | null | undefined => {
902    const selectedStruct: unknown =
903      CpuStruct.selectCpuStruct ||
904      ThreadStruct.selectThreadStruct ||
905      TraceRow.rangeSelectObject ||
906      FuncStruct.selectFuncStruct ||
907      IrqStruct.selectIrqStruct ||
908      JankStruct.selectJankStruct ||
909      AppStartupStruct.selectStartupStruct ||
910      SoStruct.selectSoStruct ||
911      SampleStruct.selectSampleStruct ||
912      GpuCounterStruct.selectGpuCounterStruct ||
913      AllAppStartupStruct.selectStartupStruct ||
914      FrameAnimationStruct.selectFrameAnimationStruct ||
915      JsCpuProfilerStruct.selectJsCpuProfilerStruct ||
916      PerfToolStruct.selectPerfToolStruct ||
917      DmaFenceStruct.selectDmaFenceStruct;
918    this.calculateSlicesTime(selectedStruct, shiftKey);
919
920    return this.slicestime;
921  };
922
923  private calculateSlicesTime(selected: unknown, shiftKey: boolean): void {
924    if (selected) {
925      let startTs = 0;
926      // @ts-ignore
927      if (selected.begin && selected.end) {
928        // @ts-ignore
929        startTs = selected.begin - selected.startTs;
930        // @ts-ignore
931        let end = selected.end - selected.startTs;
932        this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, end, shiftKey);
933        // @ts-ignore
934      } else if (selected.startNS && selected.dur) {
935        // @ts-ignore
936        startTs = selected.startNS - selected.startTime;
937        // @ts-ignore
938        let end = selected.startNS + selected.dur - selected.startTime;
939        this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, end, shiftKey);
940      } else {
941        // @ts-ignore
942        startTs = selected.startTs || selected.startTime || selected.startNS || selected.ts || 0;
943        // @ts-ignore
944        let dur = selected.dur || selected.totalTime || selected.endNS - selected.startNS || 0;
945        this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, startTs + dur, shiftKey);
946      }
947    } else {
948      this.slicestime = this.timerShaftEL?.setSlicesMark();
949    }
950  }
951
952  stopWASD = (): void => {
953    setTimeout((): void => {
954      for (let key of this.keyPressMap.keys()) {
955        if (this.keyPressMap.get(key)) {
956          this.timerShaftEL?.stopWASD({ key: key });
957          this.keyPressMap.set(key, false);
958        }
959      }
960    }, 100);
961  };
962
963  // 一直按着回车键的时候执行搜索功能
964  continueSearch = (ev: KeyboardEvent): void => {
965    if (ev.key === 'Enter') {
966      if (ev.shiftKey) {
967        this.dispatchEvent(
968          new CustomEvent('trace-previous-data', {
969            detail: { down: true },
970            composed: false,
971          })
972        );
973      } else {
974        if (this.focusTarget === '') {
975          this.dispatchEvent(
976            new CustomEvent('trace-next-data', {
977              detail: { down: true },
978              composed: false,
979            })
980          );
981        }
982      }
983    }
984  };
985
986  documentOnKeyUp = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyUp(this, ev);
987
988  /**
989   * 根据传入的参数实现卡尺和旗子的快捷跳转
990   * @param list 要跳转的数组
991   * @param type 标记类型(卡尺和旗子)
992   * @param direction 跳转方向(前一个/后一个)
993   */
994  MarkJump(list: Array<unknown>, type: string, direction: string, ev: KeyboardEvent): void {
995    this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet'); // @ts-ignore
996    let find = list.find((it) => it.selected);
997    if (!find) {
998      // 如果当前没有选中的,就选中第一个
999      // @ts-ignore
1000      list.forEach((it) => (it.selected = false));
1001      this.ifSliceInView(list[0], type, ev); // @ts-ignore
1002      list[0].selected = true;
1003    } else {
1004      for (let i = 0; i < list.length; i++) {
1005        // 将当前数组中选中的那条数据改为未选中
1006        // @ts-ignore
1007        if (list[i].selected) {
1008          // @ts-ignore
1009          list[i].selected = false;
1010          if (direction === 'previous') {
1011            if (i === 0) {
1012              // 如果当前选中的是第一个,就循环到最后一个上
1013              this.ifSliceInView(list[list.length - 1], type, ev); // @ts-ignore
1014              list[list.length - 1].selected = true;
1015              break;
1016            } else {
1017              // 选中当前的上一个
1018              this.ifSliceInView(list[i - 1], type, ev); // @ts-ignore
1019              list[i - 1].selected = true;
1020              break;
1021            }
1022          } else if (direction === 'next') {
1023            if (i === list.length - 1) {
1024              // 如果当前选中的是最后一个,就循环到第一个上
1025              this.ifSliceInView(list[0], type, ev); // @ts-ignore
1026              list[0].selected = true;
1027              break;
1028            } else {
1029              // 选中当前的下一个
1030              this.ifSliceInView(list[i + 1], type, ev); // @ts-ignore
1031              list[i + 1].selected = true;
1032              break;
1033            }
1034          }
1035        }
1036      }
1037    }
1038
1039    if (type === 'flag') {
1040      let currentPane = this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag');
1041      list.forEach((flag, index) => {
1042        // @ts-ignore
1043        this.timerShaftEL!.sportRuler!.drawTriangle(flag.time, flag.type); // @ts-ignore
1044        if (flag.selected) {
1045          // 修改当前选中的旗子对应的表格中某行的背景
1046          currentPane!.setTableSelection(index + 1);
1047        }
1048      });
1049    } else if (type === 'slice') {
1050      this.refreshCanvas(true);
1051      let currentPane = this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current');
1052      list.forEach((slice, index) => {
1053        // @ts-ignore
1054        if (slice.selected) {
1055          // 修改当前选中的卡尺对应的表格中某行的背景
1056          currentPane!.setTableSelection(index + 1);
1057        }
1058      });
1059    }
1060  }
1061
1062  ifSliceInView(data: unknown, type: string, ev: KeyboardEvent): void {
1063    let timeRangeEndNS = this.timerShaftEL?.getRangeRuler()?.range.endNS;
1064    let timeRangeStartNS = this.timerShaftEL?.getRangeRuler()?.range.startNS;
1065    if (type === 'flag') {
1066      // @ts-ignore
1067      data.startTime = data.time; // @ts-ignore
1068      data.endTime = data.time;
1069    } // @ts-ignore
1070    let endTime = data.endTime; // @ts-ignore
1071    let startTime = data.startTime;
1072    if (endTime > timeRangeEndNS! || startTime < timeRangeStartNS!) {
1073      // @ts-ignore
1074      this.timerShaftEL!.documentOnKeyPress(ev, data);
1075      setTimeout(() => {
1076        this.timerShaftEL!.documentOnKeyUp(ev);
1077      }, 1000);
1078    }
1079  }
1080
1081  isMouseInSheet = (ev: MouseEvent): boolean => {
1082    this.isMousePointInSheet =
1083      this.traceSheetEL?.getAttribute('mode') !== 'hidden' &&
1084      ev.offsetX > this.traceSheetEL!.offsetLeft &&
1085      ev.offsetY > this.traceSheetEL!.offsetTop;
1086    return this.isMousePointInSheet;
1087  };
1088  // @ts-ignore
1089  favoriteChangeHandler = (row: TraceRow<unknown>): void => {
1090    info('favoriteChangeHandler', row.frame, row.offsetTop, row.offsetHeight);
1091  };
1092
1093  /**
1094   * 根据选择的traceRow 处理foler
1095   * @param currentRow 当前点击checkbox的row
1096   */
1097  // @ts-ignore
1098  setParentCheckStatus(currentRow: TraceRow<unknown>): void {
1099    if (currentRow.parentRowEl?.folder && currentRow.parentRowEl?.childrenList) {
1100      const parent = currentRow.parentRowEl;
1101      const childrenList = parent.childrenList;
1102      const selectList = [];
1103      const unSelectList = [];
1104      for (const child of childrenList) {
1105        if (child.offsetParent === null) {
1106          continue;
1107        }
1108        if (child.checkType === '2') {
1109          selectList.push(child);
1110        } else {
1111          unSelectList.push(child);
1112        }
1113      }
1114      if (unSelectList.length === 0) {
1115        parent.setAttribute('check-type', '2');
1116        parent.rangeSelect = true;
1117        parent.checkBoxEL!.checked = true;
1118        parent.checkBoxEL!.indeterminate = false;
1119      } else if (selectList.length === 0) {
1120        parent.setAttribute('check-type', '0');
1121        parent.rangeSelect = false;
1122        parent.checkBoxEL!.checked = false;
1123        parent.checkBoxEL!.indeterminate = false;
1124      } else {
1125        parent.setAttribute('check-type', '1');
1126        parent.rangeSelect = false;
1127        parent.checkBoxEL!.checked = false;
1128        parent.checkBoxEL!.indeterminate = true;
1129      }
1130    }
1131  }
1132
1133  /**
1134   * 处理点击checkbox的逻辑
1135   * @param row 当前点击checkbox的row
1136   */
1137  // @ts-ignore
1138  selectChangeHandler = (row: TraceRow<unknown>): void => {
1139    this.setParentCheckStatus(row);
1140    const rows = [
1141      // @ts-ignore
1142      ...this.shadowRoot!.querySelectorAll<TraceRow<unknown>>("trace-row[check-type='2']"),
1143      ...this.favoriteChartListEL!.getAllSelectCollectRows(),
1144    ];
1145    this.isSelectClick = true;
1146    this.rangeSelect.rangeTraceRow = rows; // @ts-ignore
1147    let changeTraceRows: Array<TraceRow<unknown>> = [];
1148    if (this.rangeTraceRow!.length < rows.length) {
1149      // @ts-ignore
1150      rows!.forEach((currentTraceRow: TraceRow<unknown>) => {
1151        let changeFilter = this.rangeTraceRow!.filter(
1152          // @ts-ignore
1153          (prevTraceRow: TraceRow<unknown>) => prevTraceRow === currentTraceRow
1154        );
1155        if (changeFilter.length < 1) {
1156          changeTraceRows.push(currentTraceRow);
1157        }
1158      });
1159      if (changeTraceRows.length > 0) {
1160        // @ts-ignore
1161        changeTraceRows!.forEach((changeTraceRow: TraceRow<unknown>) => {
1162          let pointEvent = this.createPointEvent(changeTraceRow);
1163          SpStatisticsHttpUtil.addOrdinaryVisitAction({
1164            action: 'trace_row', // @ts-ignore
1165            event: pointEvent,
1166          });
1167        });
1168      }
1169    }
1170    this.rangeTraceRow = rows;
1171    this.rangeSelect.selectHandler?.(this.rangeSelect.rangeTraceRow, false);
1172  };
1173  inFavoriteArea: boolean | undefined;
1174  documentOnMouseMove = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseMove(this, ev);
1175
1176  hoverStructNull(): SpSystemTrace {
1177    CpuStruct.hoverCpuStruct = undefined;
1178    CpuFreqStruct.hoverCpuFreqStruct = undefined;
1179    ThreadStruct.hoverThreadStruct = undefined;
1180    FuncStruct.hoverFuncStruct = undefined;
1181    ProcessMemStruct.hoverProcessMemStruct = undefined;
1182    HiPerfCpuStruct.hoverStruct = undefined;
1183    HiPerfProcessStruct.hoverStruct = undefined;
1184    HiPerfThreadStruct.hoverStruct = undefined;
1185    HiPerfEventStruct.hoverStruct = undefined;
1186    HiPerfReportStruct.hoverStruct = undefined;
1187    CpuStateStruct.hoverStateStruct = undefined;
1188    CpuAbilityMonitorStruct.hoverCpuAbilityStruct = undefined;
1189    DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined;
1190    MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = undefined;
1191    NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = undefined;
1192    CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined;
1193    FpsStruct.hoverFpsStruct = undefined;
1194    ClockStruct.hoverClockStruct = undefined;
1195    IrqStruct.hoverIrqStruct = undefined;
1196    HeapStruct.hoverHeapStruct = undefined;
1197    JankStruct.hoverJankStruct = undefined;
1198    AppStartupStruct.hoverStartupStruct = undefined;
1199    SoStruct.hoverSoStruct = undefined;
1200    HeapSnapshotStruct.hoverSnapshotStruct = undefined;
1201    FrameAnimationStruct.hoverFrameAnimationStruct = undefined;
1202    FrameDynamicStruct.hoverFrameDynamicStruct = undefined;
1203    FrameSpacingStruct.hoverFrameSpacingStruct = undefined;
1204    JsCpuProfilerStruct.hoverJsCpuProfilerStruct = undefined;
1205    SnapshotStruct.hoverSnapshotStruct = undefined;
1206    HiPerfCallChartStruct.hoverPerfCallCutStruct = undefined;
1207    SampleStruct.hoverSampleStruct = undefined;
1208    PerfToolStruct.hoverPerfToolStruct = undefined;
1209    GpuCounterStruct.hoverGpuCounterStruct = undefined;
1210    DmaFenceStruct.hoverDmaFenceStruct = undefined;//清空hover slice
1211    this.tipEL!.style.display = 'none';
1212    return this;
1213  }
1214
1215  selectStructNull(): SpSystemTrace {
1216    CpuStruct.selectCpuStruct = undefined;
1217    CpuStruct.wakeupBean = null;
1218    CpuFreqStruct.selectCpuFreqStruct = undefined;
1219    ThreadStruct.selectThreadStruct = undefined;
1220    ThreadStruct.isClickPrio = false;
1221    FuncStruct.selectFuncStruct = undefined;
1222    SpHiPerf.selectCpuStruct = undefined;
1223    CpuStateStruct.selectStateStruct = undefined;
1224    CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = undefined;
1225    ClockStruct.selectClockStruct = undefined;
1226    HangStruct.selectHangStruct = undefined;
1227    IrqStruct.selectIrqStruct = undefined;
1228    JankStruct.selectJankStruct = undefined;
1229    HeapStruct.selectHeapStruct = undefined;
1230    AppStartupStruct.selectStartupStruct = undefined;
1231    SoStruct.selectSoStruct = undefined;
1232    HeapSnapshotStruct.selectSnapshotStruct = undefined;
1233    FrameSpacingStruct.selectFrameSpacingStruct = undefined;
1234    FrameAnimationStruct.selectFrameAnimationStruct = undefined;
1235    FrameDynamicStruct.selectFrameDynamicStruct = undefined;
1236    JsCpuProfilerStruct.selectJsCpuProfilerStruct = undefined;
1237    SnapshotStruct.selectSnapshotStruct = undefined;
1238    HiPerfCallChartStruct.selectStruct = undefined;
1239    AllAppStartupStruct.selectStartupStruct = undefined;
1240    LtpoStruct.selectLtpoStruct = undefined;
1241    HitchTimeStruct.selectHitchTimeStruct = undefined;
1242    SampleStruct.selectSampleStruct = undefined;
1243    PerfToolStruct.selectPerfToolStruct = undefined;
1244    GpuCounterStruct.selectGpuCounterStruct = undefined;
1245    DmaFenceStruct.selectDmaFenceStruct = undefined;//清空选中slice
1246    return this;
1247  }
1248
1249  isWASDKeyPress(): boolean | undefined {
1250    return (
1251      this.keyPressMap.get('w') || this.keyPressMap.get('a') || this.keyPressMap.get('d') || this.keyPressMap.get('s')
1252    );
1253  }
1254
1255  documentOnClick = (ev: MouseEvent): void => spSystemTraceDocumentOnClick(this, ev);
1256
1257  clickEmptyArea(): void {
1258    this.queryAllTraceRow().forEach((it) => {
1259      it.checkType = '-1';
1260      it.rangeSelect = false;
1261    });
1262    this.rangeSelect.rangeTraceRow = [];
1263    TraceRow.rangeSelectObject = undefined;
1264    this.selectStructNull();
1265    this.wakeupListNull();
1266    this.observerScrollHeightEnable = false;
1267    this.selectFlag = null;
1268    this.timerShaftEL?.removeTriangle('inverted');
1269    //   如果鼠标在SportRuler区域不隐藏tab页
1270    if (!SportRuler.isMouseInSportRuler) {
1271      this.traceSheetEL?.setMode('hidden');
1272    }
1273    this.removeLinkLinesByBusinessType('task', 'thread', 'func');
1274    this.removeLinkLinesByBusinessType('task', 'thread', 'distributed');
1275    this.refreshCanvas(true, 'click empty');
1276    JankStruct.delJankLineFlag = true;
1277  }
1278
1279  //泳道图点击判定条件
1280  traceRowClickJudgmentConditions: Map<string, () => boolean> = new Map<string, () => boolean>([
1281    [TraceRow.ROW_TYPE_CPU, (): boolean => CpuStruct.hoverCpuStruct !== null && CpuStruct.hoverCpuStruct !== undefined],
1282    [
1283      TraceRow.ROW_TYPE_THREAD,
1284      (): boolean => ThreadStruct.hoverThreadStruct !== null && ThreadStruct.hoverThreadStruct !== undefined,
1285    ],
1286    [
1287      TraceRow.ROW_TYPE_FUNC,
1288      (): boolean => FuncStruct.hoverFuncStruct !== null && FuncStruct.hoverFuncStruct !== undefined,
1289    ],
1290    [
1291      TraceRow.ROW_TYPE_SAMPLE,
1292      (): boolean => SampleStruct.hoverSampleStruct !== null && SampleStruct.hoverSampleStruct !== undefined,
1293    ],
1294    [
1295      TraceRow.ROW_TYPE_GPU_COUNTER,
1296      (): boolean =>
1297        GpuCounterStruct.hoverGpuCounterStruct !== null && GpuCounterStruct.hoverGpuCounterStruct !== undefined,
1298    ],
1299    [
1300      TraceRow.ROW_TYPE_CPU_FREQ,
1301      (): boolean => CpuFreqStruct.hoverCpuFreqStruct !== null && CpuFreqStruct.hoverCpuFreqStruct !== undefined,
1302    ],
1303    [
1304      TraceRow.ROW_TYPE_CPU_STATE,
1305      (): boolean => CpuStateStruct.hoverStateStruct !== null && CpuStateStruct.hoverStateStruct !== undefined,
1306    ],
1307    [
1308      TraceRow.ROW_TYPE_CPU_FREQ_LIMIT,
1309      (): boolean =>
1310        CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct !== null &&
1311        CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct !== undefined,
1312    ],
1313    [
1314      TraceRow.ROW_TYPE_CLOCK,
1315      (): boolean => ClockStruct.hoverClockStruct !== null && ClockStruct.hoverClockStruct !== undefined,
1316    ],
1317    [TraceRow.ROW_TYPE_IRQ, (): boolean => IrqStruct.hoverIrqStruct !== null && IrqStruct.hoverIrqStruct !== undefined],
1318    [
1319      TraceRow.ROW_TYPE_APP_STARTUP,
1320      (): boolean => AppStartupStruct.hoverStartupStruct !== null && AppStartupStruct.hoverStartupStruct !== undefined,
1321    ],
1322    [
1323      TraceRow.ROW_TYPE_ALL_APPSTARTUPS,
1324      (): boolean =>
1325        AllAppStartupStruct.hoverStartupStruct !== null && AllAppStartupStruct.hoverStartupStruct !== undefined,
1326    ],
1327    [
1328      TraceRow.ROW_TYPE_STATIC_INIT,
1329      (): boolean => SoStruct.hoverSoStruct !== null && SoStruct.hoverSoStruct !== undefined,
1330    ],
1331    [
1332      TraceRow.ROW_TYPE_JANK,
1333      (): boolean => JankStruct.hoverJankStruct !== null && JankStruct.hoverJankStruct !== undefined,
1334    ],
1335    [
1336      TraceRow.ROW_TYPE_HEAP,
1337      (): boolean => HeapStruct.hoverHeapStruct !== null && HeapStruct.hoverHeapStruct !== undefined,
1338    ],
1339    [
1340      TraceRow.ROW_TYPE_SYS_MEMORY_GPU_TOTAL,
1341      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1342    ],
1343    [
1344      TraceRow.ROW_TYPE_SYS_MEMORY_GPU_WINDOW,
1345      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1346    ],
1347    [
1348      TraceRow.ROW_TYPE_HEAP_SNAPSHOT,
1349      (): boolean =>
1350        HeapSnapshotStruct.hoverSnapshotStruct !== null && HeapSnapshotStruct.hoverSnapshotStruct !== undefined,
1351    ],
1352    [
1353      TraceRow.ROW_TYPE_FRAME_ANIMATION,
1354      (): boolean =>
1355        FrameAnimationStruct.hoverFrameAnimationStruct !== null &&
1356        FrameAnimationStruct.hoverFrameAnimationStruct !== undefined,
1357    ],
1358    [
1359      TraceRow.ROW_TYPE_FRAME_DYNAMIC,
1360      (): boolean =>
1361        FrameDynamicStruct.hoverFrameDynamicStruct !== null && FrameDynamicStruct.hoverFrameDynamicStruct !== undefined,
1362    ],
1363    [
1364      TraceRow.ROW_TYPE_FRAME_SPACING,
1365      (): boolean =>
1366        FrameSpacingStruct.hoverFrameSpacingStruct !== null && FrameSpacingStruct.hoverFrameSpacingStruct !== undefined,
1367    ],
1368    [
1369      TraceRow.ROW_TYPE_JS_CPU_PROFILER,
1370      (): boolean =>
1371        JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== null &&
1372        JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== undefined,
1373    ],
1374    [
1375      TraceRow.ROW_TYPE_PURGEABLE_TOTAL_ABILITY,
1376      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1377    ],
1378    [
1379      TraceRow.ROW_TYPE_PURGEABLE_PIN_ABILITY,
1380      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1381    ],
1382    [
1383      TraceRow.ROW_TYPE_PURGEABLE_TOTAL_VM,
1384      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1385    ],
1386    [
1387      TraceRow.ROW_TYPE_PURGEABLE_PIN_VM,
1388      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1389    ],
1390    [
1391      TraceRow.ROW_TYPE_DMA_ABILITY,
1392      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1393    ],
1394    [
1395      TraceRow.ROW_TYPE_DMA_VMTRACKER,
1396      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1397    ],
1398    [
1399      TraceRow.ROW_TYPE_GPU_MEMORY_ABILITY,
1400      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1401    ],
1402    [
1403      TraceRow.ROW_TYPE_GPU_MEMORY_VMTRACKER,
1404      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1405    ],
1406    [
1407      TraceRow.ROW_TYPE_GPU_RESOURCE_VMTRACKER,
1408      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1409    ],
1410    [
1411      TraceRow.ROW_TYPE_VMTRACKER_SHM,
1412      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1413    ],
1414    [
1415      TraceRow.ROW_TYPE_VM_TRACKER_SMAPS,
1416      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1417    ],
1418  ]);
1419
1420  // @ts-ignore
1421  onClickHandler(clickRowType: string, row?: TraceRow<unknown>, entry?: unknown): void {
1422    spSystemTraceOnClickHandler(this, clickRowType, row as TraceRow<BaseStruct>, entry);
1423  }
1424
1425  makePoint(
1426    ts: number,
1427    dur: number,
1428    translateY: number,
1429    rowStruct: unknown,
1430    offsetY: number,
1431    business: string,
1432    lineType: LineType,
1433    isRight: boolean
1434  ): PairPoint {
1435    return {
1436      x: ns2xByTimeShaft(ts + dur, this.timerShaftEL!),
1437      y: translateY!,
1438      offsetY: offsetY,
1439      ns: ts + dur, // @ts-ignore
1440      rowEL: rowStruct!,
1441      isRight: isRight,
1442      business: business,
1443      lineType: lineType,
1444    };
1445  }
1446  // @ts-ignore
1447  drawTaskPollLine(row?: TraceRow<unknown>): void {
1448    spSystemTraceDrawTaskPollLine(this, row);
1449  }
1450  drawJankLine(
1451    endParentRow: unknown,
1452    selectJankStruct: JankStruct,
1453    data: unknown,
1454    isBinderClick: boolean = false
1455  ): void {
1456    spSystemTraceDrawJankLine(this, endParentRow, selectJankStruct, data, isBinderClick);
1457  }
1458
1459  drawDistributedLine(
1460    sourceData: FuncStruct,
1461    targetData: FuncStruct,
1462    selectFuncStruct: FuncStruct,
1463  ): void {
1464    spSystemTraceDrawDistributedLine(this, sourceData, targetData, selectFuncStruct);
1465  }
1466
1467  drawThreadLine(endParentRow: unknown, selectThreadStruct: ThreadStruct | undefined, data: unknown): void {
1468    spSystemTraceDrawThreadLine(this, endParentRow, selectThreadStruct, data);
1469  }
1470
1471  drawFuncLine(endParentRow: unknown, selectFuncStruct: FuncStruct | undefined, data: unknown, binderTid: Number): void {
1472    spSystemTraceDrawFuncLine(this, endParentRow, selectFuncStruct, data, binderTid);
1473  }
1474
1475  getStartRow(selectRowId: number | undefined, collectList: unknown[]): unknown {
1476    let startRow = this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>(
1477      `trace-row[row-id='${selectRowId}'][row-type='thread']`
1478    );
1479    if (!startRow) {
1480      for (let collectChart of collectList) {
1481        // @ts-ignore
1482        if (collectChart.rowId === selectRowId?.toString() && collectChart.rowType === 'thread') {
1483          // @ts-ignore
1484          startRow = collectChart;
1485          break;
1486        }
1487      }
1488    }
1489    return startRow;
1490  }
1491
1492  calculateStartY(startRow: unknown, pid: number | undefined, selectFuncStruct?: FuncStruct): [number, unknown, number] {
1493    // @ts-ignore
1494    let startY = startRow ? startRow!.translateY! : 0;
1495    let startRowEl = startRow;
1496    let startOffSetY = selectFuncStruct ? 20 * (0.5 + Number(selectFuncStruct.depth)) : 20 * 0.5;
1497    // @ts-ignore
1498    const startParentRow = startRow ? this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>(`trace-row[row-id='${startRow.rowParentId}'][folder]`) : this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>(
1499      `trace-row[row-id='${pid}'][folder]`
1500    );
1501    const expansionFlag = this.collectionHasThread(startRow);
1502    if (startParentRow && !startParentRow.expansion && expansionFlag) {
1503      startY = startParentRow.translateY!;
1504      startRowEl = startParentRow;
1505      startOffSetY = selectFuncStruct ? 10 * (0.5 + Number(selectFuncStruct.depth)) : 10 * 0.5;
1506    }
1507    return [startY, startRowEl, startOffSetY];
1508  }
1509
1510  calculateEndY(endParentRow: unknown, endRowStruct: unknown, data?: unknown): [number, unknown, number] {
1511    // @ts-ignore
1512    let endY = endRowStruct.translateY!;
1513    let endRowEl = endRowStruct;
1514    // @ts-ignore
1515    let endOffSetY = data ? 20 * (0.5 + Number(data.depth)) : 20 * 0.5;
1516    const expansionFlag = this.collectionHasThread(endRowStruct);
1517    // @ts-ignore
1518    if (!endParentRow.expansion && expansionFlag) {
1519      // @ts-ignore
1520      endY = endParentRow.translateY!;
1521      endRowEl = endParentRow;
1522      // @ts-ignore
1523      endOffSetY = data ? 10 * (0.5 + Number(data.depth)) : 10 * 0.5;
1524    }
1525    return [endY, endRowEl, endOffSetY];
1526  }
1527
1528  collectionHasThread(threadRow: unknown): boolean {
1529    const collectList = this.favoriteChartListEL!.getCollectRows();
1530    for (let item of collectList!) {
1531      // @ts-ignore
1532      if (threadRow && item.rowId === threadRow.rowId && item.rowType === threadRow.rowType) {
1533        return false;
1534      }
1535    }
1536    return true;
1537  }
1538
1539  translateByMouseMove(ev: MouseEvent): void {
1540    ev.preventDefault();
1541    let offset = 0;
1542    if (this.offsetMouse === 0) {
1543      this.offsetMouse = ev.clientX;
1544      offset = ev.clientX - this.mouseCurrentPosition;
1545    } else {
1546      offset = ev.clientX - this.offsetMouse;
1547    }
1548    this.offsetMouse = ev.clientX;
1549    const rangeRuler = this.timerShaftEL?.getRangeRuler()!;
1550    rangeRuler.translate(offset);
1551  }
1552
1553  private eventListener(): void {
1554    /**
1555     * 监听时间轴区间变化
1556     */
1557    this.timerShaftEL!.rangeChangeHandler = this.timerShaftELRangeChange;
1558    this.timerShaftEL!.rangeClickHandler = this.timerShaftELRangeClick;
1559    this.timerShaftEL!.flagChangeHandler = this.timerShaftELFlagChange;
1560    this.timerShaftEL!.flagClickHandler = this.timerShaftELFlagClickHandler;
1561    /**
1562     * 监听rowsEL的滚动时间,刷新可见区域的trace-row组件的时间区间(将触发trace-row组件重绘)
1563     */
1564    this.rowsPaneEL?.addEventListener('scroll', this.rowsElOnScroll, {
1565      passive: true,
1566    });
1567    this.favoriteChartListEL?.addEventListener('scroll', this.favoriteRowsElOnScroll, {
1568      passive: true,
1569    });
1570    /**
1571     * 监听document的mousemove事件 坐标通过换算后找到当前鼠标所在的trace-row组件,将坐标传入
1572     */
1573    this.addEventListener('mousemove', this.documentOnMouseMove);
1574    this.addEventListener('click', this.documentOnClick);
1575    this.addEventListener('mousedown', this.documentOnMouseDown);
1576    this.addEventListener('mouseup', this.documentOnMouseUp);
1577    this.addEventListener('mouseout', this.documentOnMouseOut);
1578    document.addEventListener('keydown', this.documentOnKeyDown);
1579    document.addEventListener('keypress', this.documentOnKeyPress);
1580    document.addEventListener('keyup', this.documentOnKeyUp);
1581    document.addEventListener('contextmenu', this.onContextMenuHandler);
1582    this.wheelListener();
1583  }
1584
1585  private subRecordExportListener(): void {
1586    window.subscribe(window.SmartEvent.UI.ExportRecord, (params) => {
1587      let range = this.timerShaftEL?.rangeRuler?.range;
1588      if (range) {
1589        let expandRows =
1590          Array.from(this.rowsEL!.querySelectorAll<TraceRow<BaseStruct>>('trace-row[folder][expansion]')) || [];
1591        let data = JSON.stringify({
1592          leftNS: range.startNS,
1593          rightNS: range.endNS,
1594          G1: this.favoriteChartListEL!.getCollectRowsInfo('1'),
1595          G2: this.favoriteChartListEL!.getCollectRowsInfo('2'),
1596          expand: expandRows.map((row) => {
1597            return {
1598              type: row.rowType,
1599              name: row.name,
1600              id: row.rowId,
1601            };
1602          }),
1603          scrollTop: this.rowsEL!.scrollTop,
1604          favoriteScrollTop: this.favoriteChartListEL!.scrollTop,
1605          //下载时存旗帜的信息
1606          drawFlag: this.timerShaftEL!.sportRuler!.flagList,
1607          //下载时存M和shiftM的信息
1608          markFlag: this.timerShaftEL!.sportRuler!.slicesTimeList,
1609        });
1610        this.downloadRecordFile(data).then(() => { });
1611      }
1612    });
1613  }
1614
1615  private async downloadRecordFile(jsonStr: string): Promise<void> {
1616    let a = document.createElement('a');
1617    let buffer = await readTraceFileBuffer();
1618    if (buffer) {
1619      let str = `MarkPositionJSON->${jsonStr}\n`;
1620      let mark = new Blob([str]);
1621      let markBuf = await mark.arrayBuffer();
1622      a.href = URL.createObjectURL(new Blob([`${markBuf.byteLength}`, mark, buffer])); // @ts-ignore
1623      a.download = (window as unknown).traceFileName || `${new Date().getTime()}`;
1624      a.click();
1625    }
1626    window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Downloading trace file with mark' });
1627  }
1628
1629  private subRecordImportListener(): void {
1630    //@ts-ignore
1631    window.subscribe(window.SmartEvent.UI.ImportRecord, (data: string) => {
1632      let record = JSON.parse(data);
1633      if (record.leftNS !== undefined && record.rightNS !== undefined) {
1634        this.favoriteChartListEL?.removeAllCollectRow();
1635        let currentGroup = this.currentCollectGroup;
1636        if (record.G1) {
1637          this.currentCollectGroup = '1';
1638          this.restoreRecordCollectRows(record.G1);
1639        }
1640        if (record.G2) {
1641          this.currentCollectGroup = '2';
1642          this.restoreRecordCollectRows(record.G2);
1643        }
1644        this.restoreRecordExpandAndTimeRange(record);
1645        this.currentCollectGroup = currentGroup;
1646        if (record.drawFlag !== undefined) {
1647          this.timerShaftEL!.sportRuler!.flagList = record.drawFlag;//获取下载时存的旗帜信息
1648          this.selectFlag = this.timerShaftEL!.sportRuler!.flagList.find((it) => it.selected);//绘制被选中旗帜对应的线
1649        }
1650        if (record.markFlag !== undefined) {
1651          this.timerShaftEL!.sportRuler!.slicesTimeList = record.markFlag;//获取下载时存的M键信息
1652        }
1653        TraceRow.range!.refresh = true;
1654        this.refreshCanvas(true);
1655        this.restoreRecordScrollTop(record.scrollTop, record.favoriteScrollTop);
1656      }
1657    });
1658  }
1659
1660  private restoreRecordExpandAndTimeRange(record: unknown): void {
1661    // @ts-ignore
1662    if (record.expand) {
1663      let expandRows = // @ts-ignore
1664        Array.from(this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row[folder][expansion]')) || [];
1665      // @ts-ignore
1666      let expands: Array<unknown> = record.expand;
1667      //关闭不在记录中的父泳道
1668      for (let expandRow of expandRows) {
1669        if (
1670          !expands.includes(
1671            (it: unknown) =>
1672              // @ts-ignore
1673              it.id === expandRow.rowId && it.name === expandRow.name && it.type === expandRow.rowType
1674          )
1675        ) {
1676          expandRow.expansion = false;
1677        }
1678      }
1679      //展开记录的泳道
1680      // @ts-ignore
1681      for (let it of record.expand) {
1682        // @ts-ignore
1683        let traceRow = this.rowsEL!.querySelector<TraceRow<unknown>>(
1684          `trace-row[folder][row-id='${it.id}'][row-type='${it.type}']`
1685        );
1686        if (traceRow && !traceRow.expansion) {
1687          traceRow.expansion = true;
1688        }
1689      }
1690    }
1691    // @ts-ignore
1692    this.timerShaftEL?.setRangeNS(record.leftNS, record.rightNS);
1693  }
1694
1695  private restoreRecordScrollTop(mainScrollTop: number, favoriteScrollTop: number): void {
1696    if (mainScrollTop && mainScrollTop > 0) {
1697      this.rowsPaneEL!.scroll({
1698        top: mainScrollTop,
1699        left: 0,
1700        behavior: 'smooth',
1701      });
1702    }
1703    if (favoriteScrollTop && favoriteScrollTop > 0) {
1704      this.favoriteChartListEL?.scroll({
1705        top: favoriteScrollTop,
1706        left: 0,
1707        behavior: 'smooth',
1708      });
1709    }
1710  }
1711
1712  private restoreRecordCollectRows(group: Array<unknown>): void {
1713    group.forEach((it: unknown) => {
1714      // @ts-ignore
1715      let traceRow: TraceRow<unknown> | undefined | null = this.rowsEL!.querySelector<TraceRow<unknown>>( // @ts-ignore
1716        `trace-row[row-id='${it.id}'][row-type='${it.type}']`
1717      );
1718      if (traceRow === null || traceRow === undefined) {
1719        // @ts-ignore
1720        if (it.parents.length > 0) {
1721          // @ts-ignore
1722          let rootFolder = it.parents[0]; // @ts-ignore
1723          let folderRow: TraceRow<unknown> | undefined | null = this.rowsEL!.querySelector<TraceRow<unknown>>(
1724            `trace-row[row-id='${rootFolder.id}'][row-type='${rootFolder.type}']`
1725          );
1726          if (folderRow) {
1727            if (!folderRow!.expansion) {
1728              folderRow!.expansion = true;
1729            } // @ts-ignore
1730            for (let i = 1; i < it.parents.length; i++) {
1731              folderRow = folderRow!.childrenList.find(
1732                // @ts-ignore
1733                (child) => child.rowId === it.parents[i].id && child.rowType === it.parents[i].type
1734              );
1735              if (!folderRow!.expansion) {
1736                folderRow!.expansion = true;
1737              }
1738            }
1739          }
1740          if (folderRow) {
1741            // @ts-ignore
1742            traceRow = folderRow.childrenList.find((child) => child.rowId === it.id && child.rowType === it.type);
1743          }
1744        }
1745      }
1746      if (traceRow) {
1747        traceRow.collectEL?.click();
1748      }
1749    });
1750  }
1751
1752  private wheelListener(): void {
1753    document.addEventListener(
1754      'wheel',
1755      (e): void => {
1756        if (e.ctrlKey) {
1757          if (e.deltaY > 0) {
1758            e.preventDefault();
1759            e.stopPropagation();
1760            let eventS = new KeyboardEvent('keypress', {
1761              key: 's',
1762              code: '83',
1763              keyCode: 83,
1764            });
1765            this.timerShaftEL!.documentOnKeyPress(eventS);
1766            setTimeout(() => this.timerShaftEL!.documentOnKeyUp(eventS), 200);
1767          }
1768          if (e.deltaY < 0) {
1769            e.preventDefault();
1770            e.stopPropagation();
1771            let eventW = new KeyboardEvent('keypress', {
1772              key: 'w',
1773              code: '87',
1774              keyCode: 87,
1775            });
1776            this.timerShaftEL!.documentOnKeyPress(eventW);
1777            setTimeout(() => this.timerShaftEL!.documentOnKeyUp(eventW), 200);
1778          }
1779        }
1780      },
1781      { passive: false }
1782    );
1783  }
1784
1785  connectedCallback(): void {
1786    this.initPointToEvent();
1787    this.eventListener();
1788    this.subRecordExportListener();
1789    this.subRecordImportListener();
1790    /**
1791     * 泳道图中添加ctrl+鼠标滚轮事件,对泳道图进行放大缩小。
1792     * 鼠标滚轮事件转化为键盘事件,keyPress和keyUp两个事件需要配合使用,
1793     * 否则泳道图会一直放大或一直缩小。
1794     * setTimeout()函数中的时间参数可以控制鼠标滚轮的频率。
1795     */
1796    SpApplication.skinChange2 = (val: boolean): void => {
1797      this.timerShaftEL?.render();
1798    };
1799    window.subscribe(window.SmartEvent.UI.UploadSOFile, (data): void => {
1800      this.chartManager?.importSoFileUpdate().then(() => {
1801        window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Import So File' });
1802        let updateCanvas = this.traceSheetEL?.updateRangeSelect();
1803        if (updateCanvas) {
1804          this.refreshCanvas(true);
1805        }
1806      });
1807    });
1808    window.subscribe(window.SmartEvent.UI.KeyPath, (data): void => {
1809      this.invisibleRows.forEach((it) => (it.needRefresh = true));
1810      this.visibleRows.forEach((it) => (it.needRefresh = true)); //@ts-ignore
1811      if (data.length === 0) {
1812        // clear
1813        SpSystemTrace.keyPathList = [];
1814        this.refreshCanvas(false);
1815      } else {
1816        // draw
1817        //@ts-ignore
1818        queryCpuKeyPathData(data).then((res): void => {
1819          SpSystemTrace.keyPathList = res;
1820          this.refreshCanvas(false);
1821        });
1822      }
1823    });
1824    window.subscribe(window.SmartEvent.UI.CheckALL, (data): void => {
1825      //@ts-ignore
1826      this.getCollectRows((row) => row.rowParentId === data.rowId).forEach((it) => {
1827        //@ts-ignore
1828        it.checkType = data.isCheck ? '2' : '0';
1829      });
1830    });
1831    window.subscribe(window.SmartEvent.UI.HoverNull, () => this.hoverStructNull());
1832    this.subscribeBottomTabVisibleEvent();
1833  }
1834
1835  private scrollH: number = 0;
1836
1837  subscribeBottomTabVisibleEvent(): void {
1838    //@ts-ignore
1839    window.subscribe(window.SmartEvent.UI.ShowBottomTab, (data: { show: number; delta: number }): void => {
1840      if (data.show === 1) {
1841        //显示底部tab
1842        this.scrollH = this.rowsEL!.scrollHeight;
1843      } else {
1844        // 底部 tab 为 最小化 或者隐藏 时候
1845        if (this.rowsEL!.scrollHeight > this.scrollH) {
1846          this.rowsEL!.scrollTop = this.rowsEL!.scrollTop - data.delta;
1847        }
1848      }
1849    });
1850  }
1851  // @ts-ignore
1852  favoriteAreaSearchHandler(row: TraceRow<unknown>): void {
1853    if (this.timerShaftEL!.collecBtn!.hasAttribute('close')) {
1854      this.timerShaftEL!.collecBtn!.removeAttribute('close');
1855      this.favoriteChartListEL!.showCollectArea();
1856    }
1857    this.favoriteChartListEL?.expandSearchRowGroup(row);
1858  }
1859
1860  scrollToProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true): void {
1861    let id = Utils.getDistributedRowId(rowId);
1862    let parentId = Utils.getDistributedRowId(rowParentId);
1863    let traceRow = // @ts-ignore
1864      this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${id}'][row-type='${rowType}']`) ||
1865      this.favoriteChartListEL!.getCollectRow((row) => row.rowId === id && row.rowType === rowType);
1866    if (traceRow?.collect) {
1867      this.favoriteChartListEL!.scroll({
1868        top:
1869          (traceRow?.offsetTop || 0) -
1870          this.favoriteChartListEL!.getCanvas()!.offsetHeight +
1871          (traceRow?.offsetHeight || 0),
1872        left: 0,
1873        behavior: smooth ? 'smooth' : undefined,
1874      });
1875    } else {
1876      // @ts-ignore
1877      let row = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${parentId}'][folder]`);
1878      if (row && !row.expansion) {
1879        row.expansion = true;
1880      }
1881      if (traceRow && traceRow.offsetTop >= 0 && traceRow.offsetHeight >= 0) {
1882        this.rowsPaneEL!.scroll({
1883          top: (traceRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + (traceRow?.offsetHeight || 0),
1884          left: 0,
1885          behavior: smooth ? 'smooth' : undefined,
1886        });
1887      }
1888    }
1889  }
1890
1891  scrollToDepth(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true, depth: number): void {
1892    let rootRow = // @ts-ignore
1893      this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`) ||
1894      this.favoriteChartListEL!.getCollectRow((row) => row.rowId === rowId && row.rowType === rowType);
1895    if (rootRow && rootRow!.collect) {
1896      this.favoriteAreaSearchHandler(rootRow);
1897      rootRow.expandFunc(rootRow, this);
1898      if (!this.isInViewport(rootRow)) {
1899        setTimeout(() => {
1900          rootRow!.scrollIntoView({ behavior: 'smooth' });
1901        }, 500);
1902      }
1903    } else {
1904      // @ts-ignore
1905      let row = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowParentId}'][folder]`);
1906      if (row && !row.expansion) {
1907        row.expansion = true;
1908      }
1909      if (rootRow) {
1910        rootRow.expandFunc(rootRow, this);
1911      }
1912      setTimeout(() => {
1913        rootRow!.scrollIntoView({ behavior: 'smooth', block: 'center' });
1914      }, 500);
1915    }
1916  }
1917
1918  isInViewport(e: unknown): boolean {
1919    // @ts-ignore
1920    const rect = e.getBoundingClientRect();
1921    return (
1922      rect.top >= 0 &&
1923      rect.left >= 0 &&
1924      rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
1925      rect.right <= (window.innerWidth || document.documentElement.clientWidth)
1926    );
1927  }
1928
1929  scrollToFunction(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true): void {
1930    let id = Utils.getDistributedRowId(rowId);
1931    let parentId = Utils.getDistributedRowId(rowParentId);
1932    let condition = `trace-row[row-id='${id}'][row-type='${rowType}'][row-parent-id='${parentId}']`;
1933    let rootRow = // @ts-ignore
1934      this.rowsEL!.querySelector<TraceRow<unknown>>(condition) ||
1935      this.favoriteChartListEL!.getCollectRow((row) => {
1936        return row.rowId === id && row.rowType === rowType && row.rowParentId === parentId;
1937      });
1938    if (rootRow?.collect) {
1939      this.favoriteAreaSearchHandler(rootRow);
1940      this.favoriteChartListEL!.scroll({
1941        top:
1942          (rootRow?.offsetTop || 0) -
1943          this.favoriteChartListEL!.getCanvas()!.offsetHeight +
1944          (rootRow?.offsetHeight || 0),
1945        left: 0,
1946        behavior: smooth ? 'smooth' : undefined,
1947      });
1948    } else {
1949      // @ts-ignore
1950      let row = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowParentId}'][folder]`);
1951      if (row && !row.expansion) {
1952        row.expansion = true;
1953      }
1954      if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) {
1955        this.rowsPaneEL!.scroll({
1956          top: (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + 20,
1957          left: 0,
1958          behavior: smooth ? 'smooth' : undefined,
1959        });
1960      }
1961    }
1962  }
1963
1964  disconnectedCallback(): void {
1965    this.timerShaftEL?.removeEventListener('range-change', this.timerShaftELRangeChange);
1966    this.rowsPaneEL?.removeEventListener('scroll', this.rowsElOnScroll);
1967    this.favoriteChartListEL?.removeEventListener('scroll', this.favoriteRowsElOnScroll);
1968    this.removeEventListener('mousemove', this.documentOnMouseMove);
1969    this.removeEventListener('click', this.documentOnClick);
1970    this.removeEventListener('mousedown', this.documentOnMouseDown);
1971    this.removeEventListener('mouseup', this.documentOnMouseUp);
1972    this.removeEventListener('mouseout', this.documentOnMouseOut);
1973    document.removeEventListener('keypress', this.documentOnKeyPress);
1974    document.removeEventListener('keydown', this.documentOnKeyDown);
1975    document.removeEventListener('keyup', this.documentOnKeyUp);
1976    document.removeEventListener('contextmenu', this.onContextMenuHandler);
1977    window.unsubscribe(window.SmartEvent.UI.SliceMark, this.sliceMarkEventHandler.bind(this));
1978  }
1979
1980  sliceMarkEventHandler(ev: unknown): void {
1981    SpSystemTrace.sliceRangeMark = ev; // @ts-ignore
1982    let startNS = ev.timestamp - (window as unknown).recordStartNS; // @ts-ignore
1983    let endNS = ev.maxDuration + startNS;
1984    TraceRow.rangeSelectObject = {
1985      startX: 0,
1986      startNS: startNS,
1987      endNS: endNS,
1988      endX: 0,
1989    };
1990    window.publish(window.SmartEvent.UI.MenuTrace, {});
1991    window.publish(window.SmartEvent.UI.TimeRange, {
1992      // @ts-ignore
1993      startNS: startNS - ev.maxDuration, // @ts-ignore
1994      endNS: endNS + ev.maxDuration,
1995    });
1996    this.queryAllTraceRow().forEach((it) => (it.checkType = '-1'));
1997    this.rangeSelect.rangeTraceRow = [];
1998    this.selectStructNull();
1999    this.wakeupListNull();
2000    this.traceSheetEL?.setMode('hidden');
2001    this.removeLinkLinesByBusinessType('janks');
2002    this.removeLinkLinesByBusinessType('distributed');
2003    TraceRow.range!.refresh = true;
2004    this.refreshCanvas(false, 'slice mark event');
2005  }
2006
2007  loadDatabaseUrl(
2008    url: string,
2009    progress: Function,
2010    complete?: ((res: { status: boolean; msg: string }) => void) | undefined
2011  ): void {
2012    this.observerScrollHeightEnable = false;
2013    this.init({ url: url }, '', progress, false).then((res) => {
2014      if (complete) {
2015        // @ts-ignore
2016        complete(res);
2017        window.publish(window.SmartEvent.UI.MouseEventEnable, {
2018          mouseEnable: true,
2019        });
2020      }
2021    });
2022  }
2023
2024  loadDatabaseArrayBuffer(
2025    buf: ArrayBuffer,
2026    thirdPartyWasmConfigUrl: string,
2027    progress: (name: string, percent: number) => void,
2028    isDistributed: boolean,
2029    complete?: ((res: { status: boolean; msg: string }) => void) | undefined,
2030    buf2?: ArrayBuffer,
2031    fileName1?: string,
2032    fileName2?: string
2033  ): void {
2034    this.observerScrollHeightEnable = false;
2035    if (isDistributed) {
2036      this.timerShaftEL?.setAttribute('distributed', '');
2037    } else {
2038      this.timerShaftEL?.removeAttribute('distributed');
2039    }
2040    this.init({ buf, buf2, fileName1, fileName2 }, thirdPartyWasmConfigUrl, progress, isDistributed).then((res) => {
2041      // @ts-ignore
2042      this.rowsEL?.querySelectorAll('trace-row').forEach((it: unknown) => this.observer.observe(it));
2043      if (complete) {
2044        // @ts-ignore
2045        complete(res);
2046        window.publish(window.SmartEvent.UI.MouseEventEnable, {
2047          mouseEnable: true,
2048        });
2049      }
2050    });
2051  }
2052
2053  loadSample = async (ev: File): Promise<void> => {
2054    this.observerScrollHeightEnable = false;
2055    await this.initSample(ev); // @ts-ignore
2056    this.rowsEL?.querySelectorAll('trace-row').forEach((it: unknown) => this.observer.observe(it));
2057    window.publish(window.SmartEvent.UI.MouseEventEnable, {
2058      mouseEnable: true,
2059    });
2060  };
2061
2062  initSample = async (ev: File): Promise<void> => {
2063    this.rowsPaneEL!.scroll({
2064      top: 0,
2065      left: 0,
2066    });
2067    this.chartManager?.initSample(ev).then((): void => {
2068      this.loadTraceCompleted = true; // @ts-ignore
2069      this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it): void => {
2070        this.intersectionObserver?.observe(it);
2071      });
2072    });
2073  };
2074
2075  loadGpuCounter = async (ev: File): Promise<void> => {
2076    this.observerScrollHeightEnable = false;
2077    await this.initGpuCounter(ev);
2078    // @ts-ignore
2079    this.rowsEL?.querySelectorAll('trace-row').forEach((it: unknown) => this.observer.observe(it));
2080    window.publish(window.SmartEvent.UI.MouseEventEnable, {
2081      mouseEnable: true,
2082    });
2083  };
2084
2085  initGpuCounter = async (ev: File): Promise<void> => {
2086    this.rowsPaneEL!.scroll({
2087      top: 0,
2088      left: 0,
2089    });
2090    this.chartManager?.initGpuCounter(ev).then(() => {
2091      this.loadTraceCompleted = true;
2092      // @ts-ignore
2093      this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it) => {
2094        this.intersectionObserver?.observe(it);
2095      });
2096    });
2097  };
2098
2099  // @ts-ignore
2100  queryAllTraceRow<T>(selectors?: string, filter?: (row: TraceRow<unknown>) => boolean): TraceRow<unknown>[] {
2101    return [
2102      // @ts-ignore
2103      ...this.rowsEL!.querySelectorAll<TraceRow<unknown>>(selectors ?? 'trace-row'),
2104      ...this.favoriteChartListEL!.getCollectRows(filter),
2105    ];
2106  }
2107
2108  search(query: string): void {
2109    this.queryAllTraceRow().forEach((item): void => {
2110      if (query === null || query === undefined || query === '') {
2111        if (
2112          item.rowType === TraceRow.ROW_TYPE_CPU ||
2113          item.rowType === TraceRow.ROW_TYPE_CPU_FREQ ||
2114          item.rowType === TraceRow.ROW_TYPE_NATIVE_MEMORY ||
2115          item.rowType === TraceRow.ROW_TYPE_FPS ||
2116          item.rowType === TraceRow.ROW_TYPE_PROCESS ||
2117          item.rowType === TraceRow.ROW_TYPE_CPU_ABILITY ||
2118          item.rowType === TraceRow.ROW_TYPE_MEMORY_ABILITY ||
2119          item.rowType === TraceRow.ROW_TYPE_DISK_ABILITY ||
2120          item.rowType === TraceRow.ROW_TYPE_NETWORK_ABILITY
2121        ) {
2122          item.expansion = false;
2123          item.rowHidden = false;
2124        } else {
2125          item.rowHidden = true;
2126        }
2127      } else {
2128        item.rowHidden = item.name.toLowerCase().indexOf(query.toLowerCase()) < 0;
2129      }
2130    });
2131    this.visibleRows.forEach((it) => (it.rowHidden = false && it.draw(true)));
2132  }
2133
2134  async searchCPU(query: string): Promise<Array<unknown>> {
2135    let pidArr: Array<number> = [];
2136    let tidArr: Array<number> = [];
2137    let processMap = Utils.getInstance().getProcessMap(Utils.currentSelectTrace);
2138    let threadMap = Utils.getInstance().getThreadMap(Utils.currentSelectTrace);
2139    for (let key of processMap.keys()) {
2140      if (`${key}`.includes(query) || (processMap.get(key) || '').includes(query)) {
2141        pidArr.push(key);
2142      }
2143    }
2144    for (let key of threadMap.keys()) {
2145      if (`${key}`.includes(query) || (threadMap.get(key) || '').includes(query)) {
2146        tidArr.push(key);
2147      }
2148    }
2149    return await searchCpuDataSender(pidArr, tidArr, Utils.currentSelectTrace);
2150  }
2151  //根据seach的内容匹配异步缓存数据中那些符合条件
2152  seachAsyncFunc(query: string): unknown[] {
2153    let asyncFuncArr: Array<unknown> = [];
2154    let strNew = (str: unknown): string => {
2155      const specialChars = {
2156        '': '\\^',
2157        '$': '\\$',
2158        '.': '\\.',
2159        '*': '\\*',
2160        '+': '\\+',
2161        '?': '\\?',
2162        '-': '\\-',
2163        '|': '\\|',
2164        '(': '\\(',
2165        ')': '\\)',
2166        '[': '\\[',
2167        ']': '\\]',
2168        '{': '\\{',
2169        '}': '\\}',
2170      };
2171      // @ts-ignore
2172      return str.replace(/[$\^.*+?|()\[\]{}-]/g, (match: string) => specialChars[match as keyof typeof specialChars]); // 类型断言
2173    };
2174    let regex = new RegExp(strNew(query), 'i');
2175    SpProcessChart.asyncFuncCache.forEach((item: unknown) => {
2176      // @ts-ignore
2177      if (regex.test(item.funName)) {
2178        asyncFuncArr.push(item);
2179      }
2180    });
2181    return asyncFuncArr;
2182  }
2183
2184  async searchFunction(cpuList: Array<unknown>, asynList: Array<unknown>, query: string): Promise<Array<unknown>> {
2185    let processList: Array<string> = [];
2186    let traceRow = // @ts-ignore
2187      this.shadowRoot!.querySelector<TraceRow<unknown>>('trace-row[scene]') ||
2188      this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene'));
2189    if (traceRow) {
2190      // @ts-ignore
2191      this.shadowRoot!.querySelectorAll<TraceRow<unknown>>("trace-row[row-type='process'][scene]").forEach(
2192        (row): void => {
2193          let rowId = row.rowId;
2194          if (rowId && rowId.includes('-')) {
2195            rowId = rowId.split('-')[0];
2196          }
2197          processList.push(rowId as string);
2198        }
2199      );
2200      if (query.includes('_')) {
2201        query = query.replace(/_/g, '\\_');
2202      }
2203      if (query.includes('%')) {
2204        query = query.replace(/%/g, '\\%');
2205      }
2206      let list = await querySceneSearchFunc(query, processList);
2207      cpuList = cpuList.concat(asynList);
2208      cpuList = cpuList.concat(list); // @ts-ignore
2209      cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0));
2210      return cpuList;
2211    } else {
2212      let list = await querySearchFunc(query);
2213      cpuList = cpuList.concat(asynList);
2214      cpuList = cpuList.concat(list); // @ts-ignore
2215      cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0));
2216      return cpuList;
2217    }
2218  }
2219
2220  searchTargetTraceHandler(): void {
2221    if (Utils.currentSelectTrace) {
2222      // @ts-ignore
2223      let traceFolder1 = this.shadowRoot!.querySelector<TraceRow<unknown>>(`trace-row[row-id='trace-1']`);
2224      // @ts-ignore
2225      let traceFolder2 = this.shadowRoot!.querySelector<TraceRow<unknown>>(`trace-row[row-id='trace-2']`);
2226      if (Utils.currentSelectTrace === '1') {
2227        if (traceFolder2?.expansion) {
2228          traceFolder2!.expansion = false;
2229        }
2230        traceFolder1!.expansion = true;
2231      } else {
2232        if (traceFolder1?.expansion) {
2233          traceFolder1!.expansion = false;
2234        }
2235        traceFolder2!.expansion = true;
2236      }
2237    }
2238  }
2239
2240  searchSdk(dataList: Array<unknown>, query: string): Array<unknown> {
2241    let traceRow = // @ts-ignore
2242      this.shadowRoot!.querySelector<TraceRow<unknown>>('trace-row[scene]') ||
2243      this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene'));
2244    let dataAll = "trace-row[row-type^='sdk']";
2245    if (traceRow) {
2246      dataAll = "trace-row[row-type^='sdk'][scene]";
2247    }
2248    let allTraceRow: unknown = []; // @ts-ignore
2249    let parentRows = this.shadowRoot!.querySelectorAll<TraceRow<unknown>>(`${dataAll}`); // @ts-ignore
2250    parentRows.forEach((parentRow: TraceRow<unknown>): void => {
2251      // @ts-ignore
2252      allTraceRow.push(parentRow);
2253      if (parentRow.childrenList && parentRow.childrenList.length > 0) {
2254        // @ts-ignore
2255        allTraceRow.push(...parentRow.childrenList);
2256      }
2257    }); // @ts-ignore
2258    allTraceRow.forEach((row: unknown): void => {
2259      // @ts-ignore
2260      if (row!.name.indexOf(query) >= 0) {
2261        let searchSdkBean = new SearchSdkBean();
2262        searchSdkBean.startTime = TraceRow.range!.startNS;
2263        searchSdkBean.dur = TraceRow.range!.totalNS; // @ts-ignore
2264        searchSdkBean.name = row.name; // @ts-ignore
2265        searchSdkBean.rowId = row.rowId;
2266        searchSdkBean.type = 'sdk'; // @ts-ignore
2267        searchSdkBean.rowType = row.rowType; // @ts-ignore
2268        searchSdkBean.rowParentId = row.rowParentId;
2269        dataList.push(searchSdkBean);
2270      }
2271    });
2272    return dataList;
2273  }
2274
2275  showStruct(previous: boolean, currentIndex: number, structs: Array<unknown>, retargetIndex?: number): number {
2276    return spSystemTraceShowStruct(this, previous, currentIndex, structs, retargetIndex);
2277  }
2278
2279  private toTargetDepth = (entry: unknown, funcRowID: string, funcStract: unknown): void => {
2280    if (entry) {
2281      this.hoverStructNull();
2282      this.selectStructNull();
2283      this.wakeupListNull();
2284      // @ts-ignore
2285      FuncStruct.hoverFuncStruct = entry; // @ts-ignore
2286      FuncStruct.selectFuncStruct = entry;
2287      this.scrollToDepth(
2288        `${funcRowID}`, // @ts-ignore
2289        `${Utils.getDistributedRowId(funcStract.pid)}`,
2290        'func',
2291        true, // @ts-ignore
2292        entry.depth || 0
2293      );
2294      // 鼠标左键点击不需要触发点击事件
2295      if (FuncStruct.funcSelect) {
2296        this.onClickHandler(TraceRow.ROW_TYPE_FUNC, undefined, entry);
2297      } // @ts-ignore
2298      FuncStruct.funcSelect = true;
2299    }
2300  };
2301
2302  scrollToActFunc(funcStract: unknown, highlight: boolean): void {
2303    if (!Utils.isBinder(funcStract)) {
2304      // @ts-ignore
2305      if (funcStract.dur === -1 || funcStract.dur === null || funcStract.dur === undefined) {
2306        // @ts-ignore
2307        funcStract.dur = (TraceRow.range?.totalNS || 0) - (funcStract.startTs || 0); // @ts-ignore
2308        funcStract.flag = 'Did not end';
2309      }
2310    }
2311    //@ts-ignore
2312    let funId = funcStract.row_id === null ? `${funcStract.funName}-${funcStract.pid}` : funcStract.row_id;
2313    //@ts-ignore
2314    let funcRowID = (funcStract.cookie === null || funcStract.cookie === undefined) ? `${Utils.getDistributedRowId(funcStract.tid)}` : funId;
2315    let targetRow = this.favoriteChartListEL?.getCollectRow((row) => {
2316      return row.rowId === funcRowID && row.rowType === 'func';
2317    });
2318    if (targetRow) {
2319      targetRow.fixedList[0] = funcStract;
2320      targetRow.highlight = highlight;
2321      //如果目标泳道图在收藏上面,则跳转至收藏
2322      this.toTargetDepth(funcStract, funcRowID, funcStract);
2323      return;
2324    }
2325    let parentRow = this.rowsEL!.querySelector<TraceRow<BaseStruct>>(
2326      // @ts-ignore
2327      `trace-row[row-id='${Utils.getDistributedRowId(funcStract.pid)}'][folder]`
2328    );
2329    if (!parentRow) {
2330      return;
2331    }
2332    let filterRow = parentRow.childrenList.filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0];
2333    if (!filterRow) {
2334      // @ts-ignore
2335      let funcRow = this.rowsEL?.querySelector<TraceRow<unknown>>(`trace-row[row-id='${funcRowID}'][row-type='func']`);
2336      if (funcRow) {
2337        filterRow = funcRow;
2338      } else {
2339        return;
2340      }
2341    }
2342    filterRow.fixedList = [funcStract];
2343    filterRow!.highlight = highlight;
2344    let row = this.rowsEL!.querySelector<TraceRow<BaseStruct>>( // @ts-ignore
2345      `trace-row[row-id='${Utils.getDistributedRowId(funcStract.pid)}'][folder]`
2346    );
2347    this.currentRow = row;
2348    if (row && !row.expansion) {
2349      row.expansion = true;
2350    }
2351    const completeEntry = (): void => {
2352      this.toTargetDepth(filterRow.fixedList[0], funcRowID, funcStract);
2353    };
2354    if (filterRow!.isComplete) {
2355      completeEntry();
2356    } else {
2357      // @ts-ignore
2358      this.scrollToProcess(`${funcStract.tid}`, `${funcStract.pid}`, 'thread', false); // @ts-ignore
2359      this.scrollToFunction(`${funcStract.tid}`, `${funcStract.pid}`, 'func', true);
2360      // filterRow!.onComplete = completeEntry;
2361      completeEntry();
2362    }
2363  }
2364
2365  closeAllExpandRows(pid: string): void {
2366    let expandRows = this.rowsEL?.querySelectorAll<TraceRow<ProcessStruct>>("trace-row[row-type='process'][expansion]");
2367    expandRows?.forEach((row): void => {
2368      if (row.rowId !== pid) {
2369        row.expansion = false;
2370      }
2371    });
2372  }
2373
2374  moveRangeToLeft(startTime: number, dur: number): void {
2375    let startNS = this.timerShaftEL?.getRange()?.startNS || 0;
2376    let endNS = this.timerShaftEL?.getRange()?.endNS || 0;
2377    let harfDur = Math.trunc(endNS - startNS - dur / 2);
2378    let leftNs = startTime;
2379    let rightNs = startTime + dur + harfDur;
2380    if (startTime - harfDur < 0) {
2381      leftNs = 0;
2382      rightNs += harfDur - startTime;
2383    }
2384    this.timerShaftEL?.setRangeNS(leftNs, rightNs);
2385    TraceRow.range!.refresh = true;
2386    this.refreshCanvas(true, 'move range to left');
2387  }
2388
2389  moveRangeToCenter(startTime: number, dur: number): void {
2390    let startNS = this.timerShaftEL?.getRange()?.startNS || 0;
2391    let endNS = this.timerShaftEL?.getRange()?.endNS || 0;
2392    let harfDur = Math.trunc((endNS - startNS) / 2 - dur / 2);
2393    let leftNs = startTime - harfDur;
2394    let rightNs = startTime + dur + harfDur;
2395    if (startTime - harfDur < 0) {
2396      leftNs = 0;
2397      rightNs += harfDur - startTime;
2398    }
2399    this.timerShaftEL?.setRangeNS(leftNs, rightNs);
2400    TraceRow.range!.refresh = true;
2401    this.refreshCanvas(true, 'move range to center');
2402  }
2403
2404  rechargeCpuData(it: CpuStruct, next: CpuStruct | undefined): void {
2405    let p = Utils.getInstance().getProcessMap().get(it.processId!);
2406    let t = Utils.getInstance().getThreadMap().get(it.tid!);
2407    let slice = Utils.getInstance().getSchedSliceMap().get(`${it.id}-${it.startTime}`);
2408    if (slice) {
2409      it.end_state = slice.endState;
2410      it.priority = slice.priority;
2411    }
2412    it.processName = p;
2413    it.processCmdLine = p;
2414    it.name = t;
2415    if (next) {
2416      if (it.startTime! + it.dur! > next!.startTime! || it.dur === -1 || it.dur === null || it.dur === undefined) {
2417        it.dur = next!.startTime! - it.startTime!;
2418        it.nofinish = true;
2419      }
2420    } else {
2421      if (it.dur === -1 || it.dur === null || it.dur === undefined) {
2422        it.dur = TraceRow.range!.endNS - it.startTime!;
2423        it.nofinish = true;
2424      }
2425    }
2426  }
2427
2428  reset(progress: Function | undefined | null): void {
2429    this.visibleRows.length = 0;
2430    this.tipEL!.style.display = 'none';
2431    this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.clientWidth, this.canvasPanel!.offsetHeight);
2432    this.loadTraceCompleted = false;
2433    this.collectRows = [];
2434    this.visibleRows = [];
2435    TraceRowConfig.allTraceRowList.forEach((it) => {
2436      it.clearMemory();
2437    });
2438    TraceRowConfig.allTraceRowList = [];
2439    this.favoriteChartListEL!.reset();
2440    if (this.rowsEL) {
2441      // @ts-ignore
2442      this.rowsEL.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((row) => {
2443        row.clearMemory();
2444        this.rowsEL!.removeChild(row);
2445      });
2446    }
2447    this.traceSheetEL?.clearMemory();
2448    this.spacerEL!.style.height = '0px';
2449    this.rangeSelect.rangeTraceRow = [];
2450    SpSystemTrace.SDK_CONFIG_MAP = undefined;
2451    SpSystemTrace.sliceRangeMark = undefined;
2452    this.timerShaftEL?.displayCollect(false);
2453    this.timerShaftEL!.collecBtn!.removeAttribute('close');
2454    CpuStruct.wakeupBean = undefined;
2455    this.selectStructNull();
2456    this.hoverStructNull();
2457    this.wakeupListNull();
2458    this.traceSheetEL?.setMode('hidden');
2459    progress?.('rest timershaft', 8);
2460    this.timerShaftEL?.reset();
2461    progress?.('clear cache', 10);
2462    HeapDataInterface.getInstance().clearData();
2463    procedurePool.clearCache();
2464    Utils.clearData();
2465    InitAnalysis.getInstance().isInitAnalysis = true;
2466    procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: unknown) => { });
2467    if (threadPool) {
2468      threadPool.submitProto(QueryEnum.ClearMemoryCache, {}, (res: unknown, len: number): void => { });
2469    }
2470    if (threadPool2) {
2471      threadPool2.submitProto(QueryEnum.ClearMemoryCache, {}, (res: unknown, len: number): void => { });
2472    }
2473    this.times.clear();
2474    resetVSync();
2475    SpSystemTrace.keyPathList = [];
2476    Utils.isTransformed = false;
2477  }
2478
2479  init = async (
2480    param: { buf?: ArrayBuffer; url?: string; buf2?: ArrayBuffer; fileName1?: string; fileName2?: string },
2481    wasmConfigUri: string,
2482    progress: Function,
2483    isDistributed: boolean
2484  ): Promise<unknown> => {
2485    return spSystemTraceInit(this, param, wasmConfigUri, progress, isDistributed);
2486  };
2487  // @ts-ignore
2488  extracted(it: TraceRow<unknown>) {
2489    return (): void => {
2490      if (it.hasAttribute('expansion')) {
2491        it.childrenList.forEach((child): void => {
2492          if (child.hasAttribute('scene') && !child.collect) {
2493            child.rowHidden = false;
2494          }
2495          if (child.folder) {
2496            child.addEventListener('expansion-change', this.extracted(child));
2497          }
2498          this.intersectionObserver?.observe(child);
2499        });
2500      } else {
2501        //@ts-ignore
2502        let parentElTopHeight = it.hasParentRowEl ? //@ts-ignore
2503          (it.parentRowEl.getBoundingClientRect().top + it.parentRowEl.clientHeight) : this.rowsPaneEL!.getBoundingClientRect().top;
2504        it.childrenList.forEach((child): void => {
2505          if (child.hasAttribute('scene') && !child.collect) {
2506            child.rowHidden = true;
2507            this.intersectionObserver?.unobserve(child);
2508          }
2509          if (child.folder) {
2510            child.removeEventListener('expansion-change', this.extracted(child));
2511          }
2512        });
2513        if (it.getBoundingClientRect().top < 0) {
2514          this.rowsPaneEL!.scrollTop =
2515            this.rowsPaneEL!.scrollTop -
2516            (it.getBoundingClientRect().top * -1 + parentElTopHeight);
2517        } else if (it.getBoundingClientRect().top > 0) {
2518          this.rowsPaneEL!.scrollTop =
2519            parentElTopHeight <
2520              it.getBoundingClientRect().top ?
2521              this.rowsPaneEL!.scrollTop :
2522              this.rowsPaneEL!.scrollTop -
2523              (parentElTopHeight - it.getBoundingClientRect().top);
2524        } else {
2525          this.rowsPaneEL!.scrollTop =
2526            this.rowsPaneEL!.scrollTop -
2527            parentElTopHeight;
2528        }
2529        this.linkNodes.map((value): void => {
2530          if ('task' === value[0].business && value[0].rowEL.parentRowEl?.rowId === it.rowId) {
2531            value[0].hidden = true;
2532            value[1].hidden = true;
2533            this.clickEmptyArea();
2534          }
2535        });
2536      }
2537      this.resetDistributedLine();
2538      if (!this.collapseAll) {
2539        this.refreshCanvas(false, 'extracted');
2540      }
2541    };
2542  }
2543
2544  resetDistributedLine(): void {
2545    if (FuncStruct.selectFuncStruct) {
2546      let dataList = FuncStruct.selectLineFuncStruct;
2547      this.removeLinkLinesByBusinessType('distributed');
2548      FuncStruct.selectLineFuncStruct = dataList;
2549      for (let index = 0; index < FuncStruct.selectLineFuncStruct.length; index++) {
2550        let sourceData = FuncStruct.selectLineFuncStruct[index];
2551        if (index !== FuncStruct.selectLineFuncStruct.length - 1) {
2552          let targetData = FuncStruct.selectLineFuncStruct[index + 1];
2553          this.drawDistributedLine(sourceData, targetData, FuncStruct.selectFuncStruct!);
2554        }
2555      }
2556      this.refreshCanvas(true);
2557    }
2558  }
2559
2560  // @ts-ignore
2561  displayTip(row: TraceRow<unknown>, struct: unknown, html: string): void {
2562    let x = row.hoverX + 248;
2563    let y = row.getBoundingClientRect().top - this.getBoundingClientRect().top;
2564    if ((struct === undefined || struct === null) && this.tipEL) {
2565      this.tipEL.style.display = 'none';
2566      return;
2567    }
2568    if (this.tipEL) {
2569      this.tipEL.innerHTML = html;
2570      if (
2571        row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER ||
2572        row.rowType === TraceRow.ROW_TYPE_PERF_CALLCHART ||
2573        row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT
2574      ) {
2575        this.tipEL.style.maxWidth = `${row.clientWidth / 3} px`;
2576        this.tipEL.style.wordBreak = ' break-all';
2577        this.tipEL.style.height = 'unset';
2578        this.tipEL.style.display = 'block'; // @ts-ignore
2579        y = y + struct.depth * 20;
2580        if (row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT) {
2581          this.tipEL.style.height = 'auto';
2582          y = row.hoverY + row.getBoundingClientRect().top - this.getBoundingClientRect().top;
2583        }
2584      } else {
2585        this.tipEL.style.display = 'flex';
2586        this.tipEL.style.height = row.style.height;
2587      }
2588      if (x + this.tipEL.clientWidth > (this.canvasPanel!.clientWidth ?? 0)) {
2589        this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px) translateY(${y}px)`;
2590      } else {
2591        this.tipEL.style.transform = `translateX(${x}px) translateY(${y}px)`;
2592      }
2593    }
2594  }
2595
2596  queryCPUWakeUpList(data: WakeupBean): void {
2597    TabPaneCurrentSelection.queryCPUWakeUpListFromBean(data).then((a: unknown) => {
2598      if (a === null) {
2599        window.publish(window.SmartEvent.UI.WakeupList, SpSystemTrace.wakeupList);
2600        return null;
2601      } // @ts-ignore
2602      SpSystemTrace.wakeupList.push(a); // @ts-ignore
2603      this.queryCPUWakeUpList(a);
2604    });
2605  }
2606
2607  wakeupListNull(): SpSystemTrace {
2608    SpSystemTrace.wakeupList = [];
2609    return this;
2610  }
2611
2612  initPointToEvent(): void {
2613    spSystemTraceInitPointToEvent(this);
2614  }
2615
2616  initHtml(): string {
2617    return SpSystemTraceHtml;
2618  }
2619}
2620