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