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