• 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 unknown KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { SpSystemTrace } from './SpSystemTrace';
17import { TabPaneFrequencySample } from './trace/sheet/cpu/TabPaneFrequencySample';
18import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample';
19import { RangeSelect } from './trace/base/RangeSelect';
20import { TraceRow } from './trace/base/TraceRow';
21import { SportRuler } from './trace/timer-shaft/SportRuler';
22import { SelectionParam } from '../bean/BoxSelection';
23import { error, info } from '../../log/Log';
24import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil';
25import { queryEbpfSamplesCount, queryPlugins } from '../database/sql/Memory.sql';
26import { SpChartManager } from './chart/SpChartManager';
27import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread';
28import { FlagsConfig } from './SpFlags';
29import { threadPool, threadPool2 } from '../database/SqlLite';
30import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank';
31import { CpuStruct } from '../database/ui-worker/cpu/ProcedureWorkerCPU';
32import { PairPoint } from '../database/ui-worker/ProcedureWorkerCommon';
33import { TraceSheet } from './trace/base/TraceSheet';
34import { TimerShaftElement } from './trace/TimerShaftElement';
35import { SpChartList } from './trace/SpChartList';
36type HTMLElementAlias = HTMLElement | null | undefined;
37import { Utils } from './trace/base/Utils';
38import { fuzzyQueryFuncRowData, queryFuncRowData } from '../database/sql/Func.sql';
39import { convertTitle } from './chart/SpXpowerChart';
40
41// 所有插件以及对应的表
42const pluginArray = [
43  {
44    pluginName: 'ftrace-plugin',
45    tables: [
46      'animation', 'app_startup', 'args', 'callstack', 'clk_event_filter',
47      'clock_event_filter', 'cpu_measure_filter', 'device_info', 'dynamic_frame', 'frame_maps',
48      'frame_slice', 'gpu_slice', 'instant', 'irq', 'process_measure_filter', 'process_measure',
49      'sched_slice', 'static_initalize', 'symbols', 'syscall', 'task_pool', 'thread_state', 'dma_fence'
50    ]
51  },
52  {
53    pluginName: 'hiperf-plugin',
54    tables: [
55      'perf_callchain', 'perf_files', 'perf_report', 'perf_sample', 'perf_thread'
56    ]
57  },
58  {
59    pluginName: 'nativehook-plugin',
60    tables: [
61      'native_hook', 'native_hook_frame', 'native_hook_statistic'
62    ]
63  },
64  {
65    pluginName: 'arkTs-plugin',
66    tables: [
67      'js_config', 'js_cpu_profiler_node', 'js_cpu_profiler_sample', 'js_heap_files', 'js_heap_info', 'js_heap_location',
68      'js_heap_nodes', 'js_heap_sample', 'js_heap_string', 'js_heap_trace_function_info', 'js_heap_trace_node', 'js_heap_edges'
69    ]
70  },
71  {
72    pluginName: 'memory-plugin',
73    tables: [
74      'memory_ashmem', 'memory_cpu', 'memory_dma', 'memory_process_gpu', 'memory_profile,', 'memory_rs_image', 'memory_window_gpu', 'smaps', 'sys_event_filter', 'sys_mem_measure'
75    ]
76  },
77  {
78    pluginName: 'hisysevent-plugin',
79    tables: [
80      'app_name', 'device_state', 'hisys_all_event', 'hisys_event_measure'
81    ]
82  },
83  {
84    pluginName: 'ebpf-plugin',
85    tables: [
86      'bio_latency_sample', 'ebpf_callstack', 'file_system_sample', 'paged_memory_sample'
87    ]
88  },
89  {
90    pluginName: 'cpu-plugin',
91    tables: [
92      'cpu_usage'
93    ]
94  },
95  {
96    pluginName: 'diskio-plugin',
97    tables: [
98      'diskio'
99    ]
100  },
101  {
102    pluginName: 'hidump-plugin',
103    tables: [
104      'hidump'
105    ]
106  },
107  {
108    pluginName: 'process-plugin',
109    tables: [
110      'live_process'
111    ]
112  },
113  {
114    pluginName: 'hilog-plugin',
115    tables: [
116      'log'
117    ]
118  },
119  {
120    pluginName: 'network-plugin',
121    tables: [
122      'network'
123    ]
124  },
125  {
126    pluginName: 'xpower-plugin',
127    tables: [
128      'xpower_measure'
129    ]
130  }
131];
132
133function rightButtonOnClick(sp: SpSystemTrace, rightStar: HTMLElementAlias): unknown {
134  Object.assign(sp, {
135    ext(): string {
136      return 'Handle the right button click event';
137    },
138  });
139
140  return function (event: unknown): void {
141    if (SpSystemTrace.btnTimer) {
142      return;
143    }
144    sp.checkclick = true;
145    // 唤醒树有值则不再重复添加
146    const startIndex = CpuStruct.selectCpuStruct!.displayProcess?.indexOf('[');
147    if (SpSystemTrace.wakeupList.length === 0) {
148      SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!);
149      sp.queryCPUWakeUpList(CpuStruct.wakeupBean!);
150      CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime;
151      CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name;
152      CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId;
153      CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim() || CpuStruct.selectCpuStruct!.processName;
154      CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid;
155      sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct));
156    } else {
157      sp.wakeupListNull();
158      SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!);
159      sp.queryCPUWakeUpList(CpuStruct.wakeupBean!);
160      CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime;
161      CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name;
162      CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId;
163      CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim() || CpuStruct.selectCpuStruct!.processName;
164      CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid;
165      sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct));
166    }
167    let rightButton: HTMLElement | null | undefined = sp.traceSheetEL?.shadowRoot
168    ?.querySelector('#current-selection > tabpane-current-selection')
169    ?.shadowRoot?.querySelector('#rightButton');
170    rightButton?.blur();
171    setTimeout(() => {
172      requestAnimationFrame(() => sp.refreshCanvas(false));
173    }, 300);
174    rightStar!.style.visibility = 'visible';
175    rightStar!.style.cursor = 'pointer';
176    SpSystemTrace.btnTimer = setTimeout((): void => {
177      SpSystemTrace.btnTimer = null; // 2.清空节流阀,方便下次开启定时器
178    }, 2000);
179  };
180}
181function rightStarOnClick(sp: SpSystemTrace) {
182  return function (ev: unknown): void {
183    let wakeupLists = [];
184    wakeupLists.push(CpuStruct.selectCpuStruct?.cpu);
185    for (let wakeupBean of SpSystemTrace.wakeupList) {
186      wakeupLists.push(wakeupBean.cpu);
187    }
188    let wakeupCpuLists = Array.from(new Set(wakeupLists)).sort();
189    for (let wakeupCpu of wakeupCpuLists) {
190      // @ts-ignore
191      let cpuFavoriteRow: unknown = sp.shadowRoot?.querySelector<TraceRow<unknown>>(
192        `trace-row[row-type='cpu-data'][row-id='${Utils.getDistributedRowId(wakeupCpu)}']`
193      );
194      if (cpuFavoriteRow === null || cpuFavoriteRow === undefined) {
195        continue;
196      }
197      // @ts-ignore
198      cpuFavoriteRow!.setAttribute('collect-type', '');
199      let replaceRow = document.createElement('div');
200      // @ts-ignore
201      replaceRow.setAttribute('row-id', `${cpuFavoriteRow.rowId}-${cpuFavoriteRow.rowType}`);
202      replaceRow.setAttribute('type', 'replaceRow');
203      // @ts-ignore
204      replaceRow.setAttribute('row-parent-id', cpuFavoriteRow.rowParentId);
205      replaceRow.style.display = 'none';
206      // @ts-ignore
207      cpuFavoriteRow.rowHidden = !cpuFavoriteRow.hasAttribute('scene');
208      // @ts-ignore
209      if (sp.rowsEL!.contains(cpuFavoriteRow)) {
210        // @ts-ignore
211        sp.rowsEL!.replaceChild(replaceRow, cpuFavoriteRow);
212      }
213      // @ts-ignore
214      cpuFavoriteRow.tampName = cpuFavoriteRow.name;
215      // @ts-ignore
216      sp.favoriteChartListEL!.insertRow(cpuFavoriteRow, cpuFavoriteRow.traceId || sp.currentCollectGroup, true);
217      // @ts-ignore
218      sp.collectRows.push(cpuFavoriteRow);
219      sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0);
220      sp.currentClickRow = null;
221      // @ts-ignore
222      cpuFavoriteRow.setAttribute('draggable', 'true');
223      // @ts-ignore
224      cpuFavoriteRow.addEventListener('dragstart', cpuFavoriteRowDragStart(sp, cpuFavoriteRow));
225      // @ts-ignore
226      cpuFavoriteRow.addEventListener('dragover', cpuFavoriteRowDragOver(sp));
227      // @ts-ignore
228      cpuFavoriteRow.addEventListener('drop', cpuFavoriteRowDropHandler(sp, cpuFavoriteRow));
229      // @ts-ignore
230      cpuFavoriteRow.addEventListener('dragend', cpuFavoriteRowDragendHandler(sp));
231    }
232    sp.refreshFavoriteCanvas();
233    sp.refreshCanvas(true);
234  };
235}
236function cpuFavoriteRowDragStart(sp: SpSystemTrace, cpuFavoriteRow: unknown) {
237  return function (): void {
238    // @ts-ignore
239    sp.currentClickRow = cpuFavoriteRow;
240  };
241}
242function cpuFavoriteRowDragOver(sp: SpSystemTrace) {
243  return function (ev: unknown): void {
244    // @ts-ignore
245    ev.preventDefault();
246    // @ts-ignore
247    ev.dataTransfer.dropEffect = 'move';
248  };
249}
250function cpuFavoriteRowDropHandler(sp: SpSystemTrace, cpuFavoriteRow: unknown) {
251  return function (ev: unknown): void {
252    if (sp.favoriteChartListEL && sp.currentClickRow && sp.currentClickRow !== cpuFavoriteRow) {
253      // @ts-ignore
254      let rect = cpuFavoriteRow.getBoundingClientRect();
255      // @ts-ignore
256      if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) {
257        //向上移动
258        // @ts-ignore
259        sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow);
260        // @ts-ignore
261      } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) {
262        //向下移动
263        // @ts-ignore
264        sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow.nextSibling);
265      }
266      sp.refreshFavoriteCanvas();
267    }
268  };
269}
270function cpuFavoriteRowDragendHandler(sp: SpSystemTrace): () => void {
271  return function (): void {
272    sp.linkNodes.forEach((itln) => {
273      if (itln[0].rowEL.collect) {
274        itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195;
275      } else {
276        itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
277      }
278      if (itln[1].rowEL.collect) {
279        itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195;
280      } else {
281        itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
282      }
283      itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY;
284      itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY;
285    });
286    sp.currentClickRow = null;
287  };
288}
289function triangleFlagHandler(sp: SpSystemTrace): (event: unknown) => void {
290  return function (event: unknown): void {
291    //@ts-ignore
292    let temporaryTime = sp.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type);
293    //@ts-ignore
294    if (event.detail.timeCallback && temporaryTime) {
295      //@ts-ignore
296      event.detail.timeCallback(temporaryTime);
297    }
298  };
299}
300function numberCalibrationHandler(sp: SpSystemTrace): (event: unknown) => void {
301  return function (event: unknown): void {
302    // @ts-ignore
303    sp.timerShaftEL!.sportRuler!.times = event.detail.time;
304    // @ts-ignore
305    sp.timerShaftEL!.sportRuler!.counts = event.detail.counts;
306    // @ts-ignore
307    sp.timerShaftEL!.sportRuler!.durations = event.detail.durations;
308    sp.timerShaftEL!.sportRuler?.draw();
309  };
310}
311function flagChangeHandler(sp: SpSystemTrace): (event: unknown) => void {
312  return function (event: unknown): void {
313    // @ts-ignore
314    sp.timerShaftEL?.modifyFlagList(event.detail);
315    // @ts-ignore
316    if (event.detail.hidden) {
317      //@ts-ignore
318      sp.selectFlag = undefined;
319      if (sp._flagList.length <= 0) {
320        let showTab = sp.getShowTab();
321        showTab = showTab.filter((it) => it !== 'box-flag');
322        if (TraceRow.rangeSelectObject && showTab.length > 0) {
323          sp.traceSheetEL?.displayTab(...showTab);
324        } else {
325          sp.traceSheetEL?.setMode('hidden');
326        }
327      }
328      sp.refreshCanvas(true);
329    }
330  };
331}
332function slicesChangeHandler(sp: SpSystemTrace): (event: unknown) => void {
333  return function (event: unknown): void {
334    // @ts-ignore
335    sp.timerShaftEL?.modifySlicesList(event.detail);
336    // @ts-ignore
337    if (event.detail.hidden) {
338      sp.slicestime = null;
339      if (sp._slicesList.length <= 0) {
340        let showTab = sp.getShowTab();
341        showTab = showTab.filter((it) => it !== 'tabpane-current');
342        if (TraceRow.rangeSelectObject && showTab.length > 0) {
343          sp.traceSheetEL?.displayTab(...showTab);
344        } else {
345          sp.traceSheetEL?.setMode('hidden');
346        }
347      }
348      sp.refreshCanvas(true);
349    }
350  };
351}
352function collectHandler(sp: SpSystemTrace): (event: unknown) => void {
353  return function (event: unknown): void {
354    // @ts-ignore
355    let currentRow = event.detail.row;
356    if (currentRow.collect) {
357      collectHandlerYes(sp, currentRow, event);
358    } else {
359      collectHandlerNo(sp, currentRow, event);
360    }
361    sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0);
362    sp.refreshFavoriteCanvas();
363    sp.refreshCanvas(true);
364    sp.linkNodes.forEach((itln) => {
365      if (itln[0].rowEL === currentRow) {
366        if (itln[0].rowEL.collect) {
367          itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195;
368        } else {
369          itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
370        }
371        itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY;
372      } else if (itln[1].rowEL === currentRow) {
373        if (itln[1].rowEL.collect) {
374          itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195;
375        } else {
376          itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
377        }
378        itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY;
379      }
380    });
381    // 收藏夹元素拖动排序功能
382    sp.currentClickRow = null;
383    currentRow.setAttribute('draggable', 'true');
384    currentRow.addEventListener('dragstart', () => {
385      sp.currentClickRow = currentRow;
386    });
387    currentRow.addEventListener('dragover', (ev: unknown) => {
388      // @ts-ignore
389      ev.preventDefault();
390      // @ts-ignore
391      ev.dataTransfer.dropEffect = 'move';
392    });
393    currentRow.addEventListener('drop', collectHandlerDrop(sp, currentRow));
394    currentRow.addEventListener('dragend', collectHandlerDragEnd(sp));
395  };
396}
397function collectHandlerNo(sp: SpSystemTrace, currentRow: unknown, event: unknown): void {
398  // @ts-ignore
399  sp.favoriteChartListEL?.deleteRow(currentRow, event.detail.type !== 'auto-collect');
400  // @ts-ignore
401  if (event.detail.type !== 'auto-collect') {
402    // @ts-ignore
403    let rowIndex = sp.collectRows.indexOf(currentRow);
404    if (rowIndex !== -1) {
405      sp.collectRows.splice(rowIndex, 1);
406    }
407  }
408  let row = currentRow;
409  let allowExpansionRow = [];
410  // @ts-ignore
411  while (row.hasParentRowEl) {
412    // @ts-ignore
413    let parent = row.parentRowEl;
414    allowExpansionRow.push(parent);
415    row = parent;
416  }
417  if (allowExpansionRow.length === 1) {
418    for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) {
419      if (allowExpansionRow[index]?.hasAttribute('scene')) {
420        if (allowExpansionRow[index]!.expansion) {
421          allowExpansionRow[index].updateChildRowStatus();
422        } else {
423          allowExpansionRow[index].expansion = true;
424        }
425      }
426    }
427  } else {
428    for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) {
429      let currentItemRow = allowExpansionRow[index];
430      if (currentItemRow.hasAttribute('scene')) {
431        if (currentItemRow.rowParentId !== '') {
432          if (currentItemRow.expansion) {
433            currentItemRow.updateChildRowStatus();
434          } else {
435            currentItemRow.expansion = true;
436          }
437        }
438        else {
439          currentItemRow.expansion = true;
440          let number = currentItemRow.childrenList.indexOf(currentRow);
441          if (number !== -1) {// 确保 currentRow 在 childrenList 中
442            let childrenEl = currentItemRow.childrenList[number];
443            let childrenNextEl = currentItemRow.childrenList[number + 1];
444            if (childrenEl) {
445              if (childrenNextEl) {
446                currentItemRow.parentNode.insertBefore(childrenEl, currentItemRow.childrenList[number + 1]);
447              } else if (childrenEl.nextSibling) {
448                currentItemRow.parentNode.insertBefore(childrenEl, childrenEl.nextSibling);
449              } else {
450                currentItemRow.parentNode.appendChild(childrenEl);
451              }
452            }
453          }
454        }
455      }
456    }
457  }
458  allowExpansionRow.length = 0;
459  // @ts-ignore
460  let traceId = currentRow.traceId ? `${currentRow.traceId}-` : '';
461  let replaceRow = sp.rowsEL!.querySelector<HTMLCanvasElement>(
462    // @ts-ignore
463    `div[row-id='${traceId}${currentRow.rowId}-${currentRow.rowType}']`
464  );
465  // 取消收藏时,删除父亲ID
466  // @ts-ignore
467  currentRow.name = currentRow.tampName;
468  //@ts-ignore  xpower转换名称
469  if (currentRow.rowType === 'xpower-system') {
470    //@ts-ignore
471    let titleEl = currentRow.shadowRoot?.querySelector('.name') as HTMLLabelElement;
472    //@ts-ignore
473    titleEl.title = convertTitle(currentRow.tampName);
474  }
475  if (replaceRow !== null) {
476    // @ts-ignore
477    sp.rowsEL!.replaceChild(currentRow, replaceRow);
478    // @ts-ignore
479    currentRow.style.boxShadow = '0 10px 10px #00000000';
480  }
481}
482function collectHandlerYes(sp: SpSystemTrace, currentRow: unknown, event: unknown): void {
483  if (!sp.collectRows.find((find) => find === currentRow)) {
484    // @ts-ignore
485    sp.collectRows.push(currentRow);
486  }
487  let replaceRow = document.createElement('div');
488  // @ts-ignore
489  let traceId = currentRow.traceId ? `${currentRow.traceId}-` : '';
490  // @ts-ignore
491  replaceRow.setAttribute('row-id', `${traceId}${currentRow.rowId}-${currentRow.rowType}`);
492  replaceRow.setAttribute('type', 'replaceRow');
493  // @ts-ignore
494  replaceRow.setAttribute('row-parent-id', currentRow.rowParentId);
495  replaceRow.style.display = 'none';
496  // @ts-ignore
497  if (!currentRow.hasAttribute('scene')) {
498    // @ts-ignore
499    currentRow.setAttribute('row-hidden', '');
500  } else {
501    // @ts-ignore
502    currentRow.removeAttribute('row-hidden');
503  }
504  // 添加收藏时,在线程名前面追加父亲ID
505  // @ts-ignore
506  let rowParentId = currentRow.rowParentId;
507  // @ts-ignore
508  currentRow.tampName = currentRow.name;
509  if (rowParentId) {
510    // @ts-ignore
511    let parentRows = sp.shadowRoot?.querySelectorAll<TraceRow<unknown>>(`trace-row[row-id='${rowParentId}']`);
512    parentRows?.forEach((parentRow) => {
513      if (
514        parentRow?.name &&
515        // @ts-ignore
516        parentRow?.name !== currentRow.name &&
517        !parentRow.rowType!.startsWith('cpu') &&
518        !parentRow.rowType!.startsWith('thread') &&
519        !parentRow.rowType!.startsWith('func') &&
520        // @ts-ignore
521        !currentRow.name.includes(parentRow.name)
522      ) {
523        //@ts-ignore
524        currentRow.name = currentRow.protoParentId ? `${currentRow.name} (${currentRow.protoParentId})` :
525          //@ts-ignore
526          `${currentRow.name} (${parentRow.name})`;
527      }
528    });
529  }
530  // @ts-ignore
531  if (!currentRow.hasParentRowEl) {
532    // @ts-ignore
533    sp.rowsEL!.replaceChild(replaceRow, currentRow);
534  }
535  //@ts-ignore  xpower转换名称
536  if (currentRow.rowType === 'xpower-system') {
537    //@ts-ignore
538    let titleEl = currentRow.shadowRoot?.querySelector('.name') as HTMLLabelElement;
539    //@ts-ignore
540    titleEl.title = convertTitle(currentRow.tampName);
541  }
542  // @ts-ignore
543  let group = currentRow.traceId || sp.currentCollectGroup;
544  // @ts-ignore
545  sp.favoriteChartListEL?.insertRow(currentRow, group, event.detail.type !== 'auto-collect');
546}
547function collectHandlerDrop(sp: SpSystemTrace, currentRow: HTMLDivElement | undefined | null): (ev: unknown) => void {
548  return function (ev: unknown) {
549    if (sp.favoriteChartListEL !== null && sp.currentClickRow !== null && sp.currentClickRow !== currentRow) {
550      // @ts-ignore
551      let rect = currentRow!.getBoundingClientRect();
552      // @ts-ignore
553      if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) {
554        //向上移动
555        sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!);
556        // @ts-ignore
557      } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) {
558        //向下移动
559        sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!.nextSibling!);
560      }
561      sp.refreshFavoriteCanvas();
562    }
563  };
564}
565function collectHandlerDragEnd(sp: SpSystemTrace): (ev: unknown) => void {
566  return function (ev: unknown): void {
567    sp.linkNodes.forEach((itln) => {
568      if (itln[0].rowEL.collect) {
569        if (sp.timerShaftEL?._checkExpand) {
570          itln[0].rowEL.translateY =
571            itln[0].rowEL.getBoundingClientRect().top - 195 + sp.timerShaftEL._usageFoldHeight!;
572        } else {
573          itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195;
574        }
575      } else {
576        itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
577      }
578      if (itln[1].rowEL.collect) {
579        if (sp.timerShaftEL?._checkExpand) {
580          itln[1].rowEL.translateY =
581            itln[1].rowEL.getBoundingClientRect().top - 195 + sp.timerShaftEL._usageFoldHeight!;
582        } else {
583          itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195;
584        }
585      } else {
586        itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
587      }
588      itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY;
589      itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY;
590    });
591    sp.currentClickRow = null;
592  };
593}
594function selectHandler(sp: SpSystemTrace): void {
595  sp.rangeSelect.selectHandler = (rows, refreshCheckBox): void => {
596    rows.forEach((item) => {
597      sp.setAttribute('clickRow', item.rowType!);
598      sp.setAttribute('rowName', item.name);
599      sp.setAttribute('rowId', item.rowId!);
600    });
601    if (rows.length === 0) {
602      const allRows = [
603        // @ts-ignore
604        ...sp.shadowRoot!.querySelectorAll<TraceRow<unknown>>('trace-row'),
605        ...sp.favoriteChartListEL!.getAllCollectRows(),
606      ];
607      for (const row of allRows) {
608        row.checkType = '-1';
609        if (row.folder) {
610          row.childrenList.forEach((item) => {
611            row.checkType = '-1';
612          });
613        }
614      }
615      sp.refreshCanvas(true);
616      if (!SportRuler.isMouseInSportRuler) {
617        sp.traceSheetEL?.setMode('max');
618        sp.traceSheetEL?.setMode('hidden');
619      }
620      return;
621    }
622    let checkRows = rows;
623    if (!refreshCheckBox) {
624      checkRows = [
625        ...rows,
626        // @ts-ignore
627        ...sp.shadowRoot!.querySelectorAll<TraceRow<unknown>>(`trace-row[check-type='2']`),
628        ...sp.favoriteChartListEL!.getAllSelectCollectRows(),
629      ];
630    }
631    checkRows = checkRows.filter((item, index, self) => {
632      return self.findIndex(obj => obj.rowId === item.rowId && obj.rowType === item.rowType && obj.name === item.name) === index;
633    });
634    selectHandlerRefreshCheckBox(sp, checkRows, refreshCheckBox);
635    if (!sp.isSelectClick) {
636      sp.rangeTraceRow = [];
637    }
638    selectHandlerRows(sp, checkRows);
639  };
640}
641// @ts-ignore
642function selectHandlerRefreshCheckBox(sp: SpSystemTrace, rows: Array<TraceRow<unknown>>, refreshCheckBox: boolean): void {
643  if (refreshCheckBox) {
644    if (rows.length > 0) {
645      sp.queryAllTraceRow().forEach((row) => (row.checkType = '0'));
646      rows.forEach((it) => (it.checkType = '2'));
647    } else {
648      sp.queryAllTraceRow().forEach((row) => (row.checkType = '-1'));
649      return;
650    }
651  }
652}
653// @ts-ignore
654function selectHandlerRows(sp: SpSystemTrace, rows: Array<TraceRow<unknown>>): void {
655  let selection = new SelectionParam();
656  selection.traceId = Utils.currentSelectTrace;
657  selection.cpuStateRowsId = sp.stateRowsId;
658  selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0;
659  selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0;
660  selection.recordStartNs = Utils.getInstance().getRecordStartNS(Utils.currentSelectTrace);
661  rows.forEach((it) => {
662    selection.pushSelection(it, sp);
663    if (sp.rangeTraceRow!.length !== rows.length) {
664      let event = sp.createPointEvent(it);
665      SpStatisticsHttpUtil.addOrdinaryVisitAction({
666        action: 'trace_row', // @ts-ignore
667        event: event,
668      });
669    }
670    sp.setParentCheckStatus(it);
671  });
672  if (selection.diskIOipids.length > 0 && !selection.diskIOLatency) {
673    selection.promiseList.push(
674      queryEbpfSamplesCount(
675        TraceRow.rangeSelectObject?.startNS || 0,
676        TraceRow.rangeSelectObject?.endNS || 0,
677        selection.diskIOipids
678      ).then((res) => {
679        if (res.length > 0) {
680          //@ts-ignore
681          selection.fsCount = res[0].fsCount;
682          //@ts-ignore
683          selection.vmCount = res[0].vmCount;
684        }
685        return new Promise((resolve) => resolve(1));
686      })
687    );
688  }
689  sp.rangeTraceRow = rows;
690  sp.isSelectClick = false;
691  sp.selectStructNull();
692  sp.timerShaftEL?.removeTriangle('inverted');
693  if (selection.promiseList.length > 0) {
694    Promise.all(selection.promiseList).then(() => {
695      selection.promiseList = [];
696      sp.traceSheetEL?.rangeSelect(selection);
697    });
698  } else {
699    sp.traceSheetEL?.rangeSelect(selection);
700  }
701  sp.timerShaftEL!.selectionList.push(selection); // 保持选中对象,为后面的再次选中该框选区域做准备。
702  sp.selectionParam = selection;
703  sp.refreshCanvas(true);
704}
705function resizeObserverHandler(sp: SpSystemTrace): void {
706  // @ts-ignore
707  new ResizeObserver((entries) => {
708    TraceRow.FRAME_WIDTH = sp.clientWidth - 249 - sp.getScrollWidth();
709    requestAnimationFrame(() => {
710      sp.timerShaftEL?.updateWidth(sp.clientWidth - 1 - sp.getScrollWidth());
711      // @ts-ignore
712      sp.shadowRoot!.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it) => {
713        it.updateWidth(sp.clientWidth);
714      });
715    });
716  }).observe(sp);
717
718  new ResizeObserver((entries) => {
719    sp.canvasPanelConfig();
720    if (sp.traceSheetEL!.getAttribute('mode') === 'hidden') {
721      sp.timerShaftEL?.removeTriangle('triangle');
722    }
723    if (sp.favoriteChartListEL?.style.display === 'flex') {
724      sp.refreshFavoriteCanvas();
725    }
726    sp.refreshCanvas(true);
727  }).observe(sp.rowsPaneEL!);
728}
729function mutationObserverHandler(sp: SpSystemTrace): void {
730  new MutationObserver((mutations, observer) => {
731    for (const mutation of mutations) {
732      if (mutation.type === 'attributes') {
733        if (sp.style.visibility === 'visible') {
734          if (TraceRow.rangeSelectObject && SpSystemTrace.sliceRangeMark) {
735            sp.timerShaftEL?.setSlicesMark(
736              TraceRow.rangeSelectObject.startNS || 0,
737              TraceRow.rangeSelectObject.endNS || 0,
738              false
739            );
740            SpSystemTrace.sliceRangeMark = undefined;
741            window.publish(window.SmartEvent.UI.RefreshCanvas, {});
742          }
743        }
744      }
745    }
746  }).observe(sp, {
747    attributes: true,
748    childList: false,
749    subtree: false,
750  });
751}
752function intersectionObserverHandler(sp: SpSystemTrace): void {
753  sp.intersectionObserver = new IntersectionObserver(
754    (entries) => {
755      entries.forEach((it) => {
756        // @ts-ignore
757        let tr = it.target as TraceRow<unknown>;
758        // 目标元素的可见比例
759        tr.intersectionRatio = it.intersectionRatio;
760        // 判断目标元素是否可见 isIntersecting为true是可见
761        if (!it.isIntersecting) {
762          tr.sleeping = true;
763          sp.invisibleRows.indexOf(tr) === -1 && sp.invisibleRows.push(tr);
764        } else {
765          tr.sleeping = false;
766          sp.visibleRows.indexOf(tr) === -1 && sp.visibleRows.push(tr);
767        }
768      });
769      //更新可见泳道及不可见泳道值
770      sp.visibleRows = sp.visibleRows.filter((it) => !it.sleeping);
771      sp.invisibleRows = sp.invisibleRows.filter((it) => it.sleeping);
772      if (sp.handler === -1) {
773        cancelAnimationFrame(sp.handler);
774      }
775      sp.handler = requestAnimationFrame(() => sp.refreshCanvas(false));
776    },
777    { threshold: [0, 0.01, 0.99, 1] }
778  );
779}
780function observerHandler(sp: SpSystemTrace): void {
781  resizeObserverHandler(sp);
782  mutationObserverHandler(sp);
783  intersectionObserverHandler(sp);
784}
785function windowKeyDownHandler(sp: SpSystemTrace): (ev: KeyboardEvent) => void {
786  return function (ev: KeyboardEvent) {
787    if (ev.key.toLocaleLowerCase() === 'escape') {
788      sp.queryAllTraceRow().forEach((it) => {
789        it.checkType = '-1';
790      });
791      TraceRow.rangeSelectObject = undefined;
792      sp.rangeSelect.rangeTraceRow = [];
793      sp.selectStructNull();
794      sp.timerShaftEL?.setSlicesMark();
795      sp.traceSheetEL?.setMode('hidden');
796      sp.removeLinkLinesByBusinessType('janks', 'task');
797    }
798  };
799}
800function smartEventSubscribe(sp: SpSystemTrace): void {
801  window.subscribe(window.SmartEvent.UI.SliceMark, (data) => sp.sliceMarkEventHandler(data));
802  window.subscribe(window.SmartEvent.UI.TraceRowComplete, (tr) => { });
803  window.subscribe(window.SmartEvent.UI.RefreshCanvas, () => sp.refreshCanvas(false));
804  window.subscribe(window.SmartEvent.UI.KeyboardEnable, (tr) => {
805    //@ts-ignore
806    sp.keyboardEnable = tr.enable;
807    if (!sp.keyboardEnable) {
808      sp.stopWASD();
809    }
810  }); //@ts-ignore
811  window.subscribe(window.SmartEvent.UI.CollapseAllLane, (collapse: boolean) => {
812    if (!collapse) {
813      // 一键折叠之前,记录当前打开的泳道图
814      // @ts-ignore
815      sp.expandRowList = Array.from(sp.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row[folder][expansion]')) || [];
816    }
817    sp.collapseAll = true;
818    sp.setAttribute('disable', '');
819    sp.expandRowList!.forEach((it) => (it.expansion = collapse));
820    sp.collapseAll = false;
821    sp.removeAttribute('disable');
822    sp.refreshCanvas(true);
823  });
824  window.subscribe(window.SmartEvent.UI.MouseEventEnable, (tr) => {
825    //@ts-ignore
826    sp.mouseEventEnable = tr.mouseEnable;
827    if (sp.mouseEventEnable) {
828      sp.removeAttribute('disable');
829    } else {
830      sp.setAttribute('disable', '');
831    }
832  }); //@ts-ignore
833  window.subscribe(window.SmartEvent.UI.CollectGroupChange, (group: string) => (sp.currentCollectGroup = group));
834}
835
836export function documentInitEvent(sp: SpSystemTrace): void {
837  if (!document) {
838    return;
839  }
840  document.addEventListener('triangle-flag', triangleFlagHandler(sp));
841  document.addEventListener('number_calibration', numberCalibrationHandler(sp));
842  document.addEventListener('flag-change', flagChangeHandler(sp));
843  document.addEventListener('slices-change', slicesChangeHandler(sp));
844  if (sp.timerShaftEL?.collecBtn) {
845    sp.timerShaftEL.collecBtn.onclick = (): void => {
846      if (sp.timerShaftEL!.collecBtn!.hasAttribute('close')) {
847        sp.timerShaftEL!.collecBtn!.removeAttribute('close');
848        sp.favoriteChartListEL?.showCollectArea();
849      } else {
850        sp.timerShaftEL!.collecBtn!.setAttribute('close', '');
851        sp.favoriteChartListEL?.hideCollectArea();
852      }
853    };
854  }
855  document.addEventListener('collect', collectHandler(sp));
856}
857
858export function spSystemTraceInitElement(sp: SpSystemTrace): void {
859  window.subscribe(window.SmartEvent.UI.LoadFinishFrame, () => sp.drawAllLines());
860  sp.traceSheetEL = sp.shadowRoot?.querySelector<TraceSheet>('.trace-sheet');
861  if (!sp || !sp.shadowRoot || !sp.traceSheetEL) {
862    return;
863  }
864  let rightButton: HTMLElement | null | undefined = sp.traceSheetEL.shadowRoot
865    ?.querySelector('#current-selection > tabpane-current-selection')
866    ?.shadowRoot?.querySelector('#rightButton');
867  let rightStar: HTMLElement | null | undefined = sp.traceSheetEL.shadowRoot
868    ?.querySelector('#current-selection > tabpane-current-selection')
869    ?.shadowRoot?.querySelector('#right-star');
870  sp.tipEL = sp.shadowRoot.querySelector<HTMLDivElement>('.tip');
871  sp.rowsPaneEL = sp.shadowRoot.querySelector<HTMLDivElement>('.rows-pane');
872  sp.rowsEL = sp.rowsPaneEL;
873  sp.spacerEL = sp.shadowRoot.querySelector<HTMLDivElement>('.spacer');
874  sp.timerShaftEL = sp.shadowRoot.querySelector<TimerShaftElement>('.timer-shaft');
875  sp.favoriteChartListEL = sp.shadowRoot.querySelector<SpChartList>('#favorite-chart-list');
876  sp.collectEl1 = sp.favoriteChartListEL?.shadowRoot?.querySelector<HTMLDivElement>('#collect-group-1');
877  sp.groupTitle1 = sp.favoriteChartListEL?.shadowRoot?.querySelector<HTMLDivElement>('#group-1-title');
878  if (!sp.traceSheetEL.shadowRoot) {
879    return;
880  }
881  sp.tabCpuFreq = sp.traceSheetEL.shadowRoot.querySelector<TabPaneFrequencySample>('tabpane-frequency-sample');
882  sp.tabCpuState = sp.traceSheetEL.shadowRoot.querySelector<TabPaneCounterSample>('tabpane-counter-sample');
883  sp.wakeupListTbl = sp.traceSheetEL.shadowRoot?.querySelector('#current-selection > tabpane-current-selection')?.
884    shadowRoot?.querySelector('#wakeupListTbl');
885  sp.rangeSelect = new RangeSelect(sp);
886  // @ts-ignore
887  rightButton?.addEventListener('click', rightButtonOnClick(sp, rightStar));
888  rightStar?.addEventListener('click', rightStarOnClick(sp));
889  documentInitEvent(sp);
890  SpSystemTrace.scrollViewWidth = sp.getScrollWidth();
891  selectHandler(sp);
892  observerHandler(sp);
893  window.addEventListener('keydown', windowKeyDownHandler(sp));
894  sp.chartManager = new SpChartManager(sp);
895  sp.canvasPanel = sp.shadowRoot.querySelector<HTMLCanvasElement>('#canvas-panel')!;
896  sp.canvasPanelCtx = sp.canvasPanel.getContext('2d');
897  sp.canvasFavoritePanelCtx = sp.favoriteChartListEL!.context();
898  sp.canvasPanelConfig();
899  smartEventSubscribe(sp);
900}
901
902function moveRangeToCenterAndHighlight(sp: SpSystemTrace, findEntry: unknown, currentEntry: unknown): void {
903  if (findEntry) {
904    //findEntry不在range范围内,会把它移动到泳道最左侧
905    // @ts-ignore
906    if (findEntry.startTime + findEntry.dur > TraceRow.range!.endNS || findEntry.startTime < TraceRow.range!.startNS) {
907      // @ts-ignore
908      sp.moveRangeToLeft(findEntry.startTime!, findEntry.dur!);
909    }
910    cancelCurrentTraceRowHighlight(sp, currentEntry);
911    // @ts-ignore
912    if (findEntry.type === 'cpu') {
913      findEntryTypeCpu(sp, findEntry);
914      // @ts-ignore
915    } else if (findEntry.type === 'func') {
916      findEntryTypeFunc(sp, findEntry);
917      // @ts-ignore
918    } else if (findEntry.type === 'thread||process') {
919      findEntryTypeThreadProcess(sp, findEntry);
920      // @ts-ignore
921    } else if (findEntry.type === 'sdk') {
922      findEntryTypeSdk(sp, findEntry);
923    }
924  }
925}
926
927export function cancelCurrentTraceRowHighlight(sp: SpSystemTrace, currentEntry: unknown): void {
928  // @ts-ignore
929  if (currentEntry?.type === 'cpu') {
930    // @ts-ignore
931    sp.queryAllTraceRow(`trace-row[row-type='cpu-data'][row-id='${currentEntry.cpu}']`,
932      // @ts-ignore
933      (row) => row.rowType === 'cpu-data' && row.rowId === `${currentEntry.cpu}`)[0].highlight = false;
934    // @ts-ignore
935  } else if (currentEntry?.type === 'func') {
936    // @ts-ignore
937    let funId = (currentEntry.rowId === null || currentEntry.rowId === undefined) ? `${currentEntry.funName}-${currentEntry.pid}` : currentEntry.rowId;
938    // @ts-ignore
939    let funcRowID = (currentEntry.cookie === null || currentEntry.cookie === undefined) ? `${Utils.getDistributedRowId(currentEntry.tid)}` : funId;
940    // @ts-ignore
941    let parentRow = sp.queryAllTraceRow(`trace-row[row-id='${Utils.getDistributedRowId(currentEntry.pid)}'][folder]`,
942      // @ts-ignore
943      (row) => row.rowId === `trace-row[row-id='${Utils.getDistributedRowId(currentEntry.pid)}'][folder]`)[0];
944    if (!parentRow) {
945      return;
946    }
947    // @ts-ignore
948    let filterRow: TraceRow<unknown> | undefined;
949    parentRow.childrenList.forEach((item) => {
950      if (item.rowId === 'sameThreadProcess') {
951        filterRow = parentRow.childrenList.concat(item.childrenList).filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0];
952      } else {
953        filterRow = parentRow.childrenList.filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0];
954      }
955    });
956    if (!filterRow) {
957      let rowsPaneEL = document.querySelector('body > sp-application')?.shadowRoot?.querySelector('#sp-system-trace')?.shadowRoot?.querySelector('div > div.rows-pane');
958      // @ts-ignore
959      let funcRow = rowsPaneEL?.querySelector<TraceRow<unknown>>(`trace-row[row-id='${funcRowID}'][row-type='func']`);
960      if (funcRow) {
961        filterRow = funcRow;
962      } else {
963        return;
964      }
965    }
966    filterRow.highlight = false;
967    // @ts-ignore
968  } else if (currentEntry?.type === 'sdk') {
969    // @ts-ignore
970    let parentRow = sp.shadowRoot!.querySelector<TraceRow<unknown>>("trace-row[row-type='sdk'][folder]");
971    if (parentRow) {
972      let sdkRow = parentRow.childrenList.filter(
973        // @ts-ignore
974        (child) => child.rowId === currentEntry.rowId && child.rowType === currentEntry.rowType
975      )[0];
976      sdkRow!.highlight = false;
977    }
978  }
979}
980
981export function spSystemTraceShowStruct(
982  sp: SpSystemTrace,
983  previous: boolean,
984  currentIndex: number,
985  structs: Array<unknown>,
986  retargetIndex?: number
987): number {
988  if (structs.length === 0) {
989    return 0;
990  }
991  let findIndex = spSystemTraceShowStructFindIndex(previous, currentIndex, structs, retargetIndex);
992  let findEntry: unknown = structs[findIndex];
993  let currentEntry: unknown = undefined;
994  if (currentIndex >= 0) {
995    currentEntry = structs[currentIndex];
996  }
997  moveRangeToCenterAndHighlight(sp, findEntry, currentEntry);
998  return findIndex;
999}
1000
1001function spSystemTraceShowStructFindIndex(
1002  previous: boolean,
1003  currentIndex: number,
1004  structs: Array<unknown>,
1005  retargetIndex: number | undefined
1006): number {
1007  const rangeStart = TraceRow.range!.startNS;
1008  const rangeEnd = TraceRow.range!.endNS;
1009  let findIndex = -1;
1010  if (retargetIndex) {//如果Go有值,直接跳转
1011    findIndex = retargetIndex - 1;
1012  } else if (previous) {
1013    //case1:current.start在start边界以右,需要从当前项往第一项遍历,找到structs[index].start < end
1014    //@ts-ignore
1015    if (structs[currentIndex].startTime! >= Math.round(rangeStart)) {
1016      findIndex = findPreviousOne(currentIndex - 1, 0, structs);
1017      //处理当前项如果是第一项
1018      findIndex = findIndex === -1 ? structs.length - 1 : findIndex;
1019    } else {
1020      //case2:current.start在start边界以左,需要从最后一项到当前项遍历,找到structs[index].start < end
1021      findIndex = findPreviousOne(structs.length - 1, currentIndex + 1, structs);
1022    }
1023  } else {//向后查找
1024    if (currentIndex === -1) {//输入框内输入内容后第一次搜索
1025      findIndex = findNextOne(0, structs.length - 1, structs);
1026      //处理当所有的项都在start以左
1027      return findIndex === -1 ? 0 : findIndex;
1028    }
1029    //case1:current.start 在end左侧  从当前项到最后一项遍历,找到startTime>start
1030    //@ts-ignore
1031    if (structs[currentIndex].startTime! < Math.round(rangeEnd)) {//case1
1032      findIndex = findNextOne(currentIndex + 1, structs.length - 1, structs);
1033      //处理当前项是最后一项
1034      findIndex = findIndex === -1 ? 0 : findIndex;
1035    } else {
1036      //case2: current.start 在end右侧  从第一项到当前项遍历,找到startTime>start
1037      findIndex = findNextOne(0, currentIndex - 1, structs);
1038    }
1039  }
1040  return findIndex;
1041}
1042//向前查找逻辑
1043function findPreviousOne(start: number, end: number, structs: Array<unknown>): number {
1044  let findIndex = -1;
1045  const rangeEnd = TraceRow.range!.endNS;
1046  for (let i = start; i >= end; i--) {
1047    let it = structs[i];
1048    //@ts-ignore
1049    if (it.startTime! < rangeEnd) {
1050      findIndex = i;
1051      break;
1052    }
1053  }
1054  return findIndex;
1055}
1056//向后查找
1057function findNextOne(start: number, end: number, structs: Array<unknown>): number {
1058  let findIndex = -1;
1059  const rangeStart = TraceRow.range!.startNS;
1060  for (let i = start; i <= end; i++) {
1061    let it = structs[i];
1062    //@ts-ignore
1063    if (it.startTime > rangeStart) {
1064      findIndex = i;
1065      break;
1066    }
1067  }
1068  return findIndex;
1069}
1070function findEntryTypeCpu(sp: SpSystemTrace, findEntry: unknown): void {
1071  // @ts-ignore
1072  CpuStruct.selectCpuStruct = findEntry;
1073  CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct;
1074  sp.queryAllTraceRow(`trace-row[row-type='cpu-data']`, (row): boolean => row.rowType === 'cpu-data').forEach(
1075    (item): void => {
1076      // @ts-ignore
1077      if (item.rowId === `${Utils.getDistributedRowId(findEntry.cpu)}`) {
1078        sp.rechargeCpuData(
1079          // @ts-ignore
1080          findEntry, // @ts-ignore
1081          item.dataListCache.find((it) => it.startTime > findEntry.startTime)
1082        );
1083        let _findEntry = JSON.parse(JSON.stringify(findEntry));
1084        _findEntry.type = 'thread';
1085        item.fixedList = [_findEntry];
1086      }
1087      // @ts-ignore
1088      item.highlight = item.rowId === `${Utils.getDistributedRowId(findEntry.cpu)}`;
1089      item.draw(true);
1090    }
1091  );
1092  // @ts-ignore
1093  sp.scrollToProcess(`${findEntry.cpu}`, '', 'cpu-data', true);
1094  sp.onClickHandler(TraceRow.ROW_TYPE_CPU);
1095}
1096function findEntryTypeFunc(sp: SpSystemTrace, findEntry: unknown): void {
1097  sp.observerScrollHeightEnable = true;
1098  sp.scrollToActFunc(
1099    {
1100      // @ts-ignore
1101      startTs: findEntry.startTime,
1102      // @ts-ignore
1103      dur: findEntry.dur,
1104      // @ts-ignore
1105      tid: findEntry.tid,
1106      // @ts-ignore
1107      pid: findEntry.pid,
1108      // @ts-ignore
1109      depth: findEntry.depth,
1110      // @ts-ignore
1111      argsetid: findEntry.argsetid,
1112      // @ts-ignore
1113      funName: findEntry.funName,
1114      // @ts-ignore
1115      cookie: findEntry.cookie,
1116      // @ts-ignore
1117      //因异步trace分类出的rowId类型有三种,故新增row_id字段,该字段为异步方法的对应的rowId,支持搜索查询定位到该方法属于那个row,只有缓存的异步trace数据中含该字段
1118      row_id: findEntry.rowId ? findEntry.rowId : null,
1119    },
1120    true
1121  );
1122}
1123function findEntryTypeThreadProcess(sp: SpSystemTrace, findEntry: unknown): void {
1124  let threadProcessRow = sp.rowsEL?.querySelectorAll<TraceRow<ThreadStruct>>('trace-row')[0];
1125  if (threadProcessRow) {
1126    let filterRow = threadProcessRow.childrenList.filter(
1127      // @ts-ignore
1128      (row) => row.rowId === Utils.getDistributedRowId(findEntry.rowId) && row.rowId === findEntry.rowType
1129    )[0];
1130    filterRow!.highlight = true;
1131    // @ts-ignore
1132    sp.closeAllExpandRows(Utils.getDistributedRowId(findEntry.rowParentId));
1133    // @ts-ignore
1134    sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true);
1135    let completeEntry = (): void => {
1136      sp.hoverStructNull();
1137      sp.selectStructNull();
1138      sp.wakeupListNull();
1139      // @ts-ignore
1140      sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true);
1141    };
1142    if (filterRow!.isComplete) {
1143      completeEntry();
1144    } else {
1145      filterRow!.onComplete = completeEntry;
1146    }
1147  }
1148}
1149function findEntryTypeSdk(sp: SpSystemTrace, findEntry: unknown): void {
1150  // @ts-ignore
1151  let parentRow = sp.shadowRoot!.querySelector<TraceRow<unknown>>(`trace-row[row-type='sdk'][folder]`);
1152  if (parentRow) {
1153    let sdkRow = parentRow.childrenList.filter(
1154      // @ts-ignore
1155      (child) => child.rowId === findEntry.rowId && child.rowType === findEntry.rowType
1156    )[0];
1157    sdkRow!.highlight = true;
1158  }
1159  sp.hoverStructNull();
1160  sp.selectStructNull();
1161  sp.wakeupListNull();
1162  // @ts-ignore
1163  sp.onClickHandler(findEntry.rowType!);
1164  // @ts-ignore
1165  sp.closeAllExpandRows(findEntry.rowParentId);
1166  // @ts-ignore
1167  sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true);
1168}
1169async function spSystemTraceInitBuffer(
1170  sp: SpSystemTrace,
1171  param: { buf?: ArrayBuffer; Url?: string; buf2?: ArrayBuffer },
1172  wasmConfigUri: string,
1173  progress: Function
1174): Promise<{
1175  status: boolean;
1176  msg: string;
1177} | null> {
1178  if (param.buf) {
1179    let configJson = '';
1180    try {
1181      configJson = await fetch(wasmConfigUri).then((res) => res.text());
1182    } catch (e) {
1183      error('getWasmConfigFailed', e);
1184    }
1185    let parseConfig = FlagsConfig.getSpTraceStreamParseConfig();
1186    let { status, msg, sdkConfigMap } = await threadPool.initSqlite(param.buf, parseConfig, configJson, progress);
1187    if (!status) {
1188      return { status: false, msg: msg };
1189    }
1190    SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap;
1191    if (param.buf2) {
1192      let { status, msg } = await threadPool2.initSqlite(param.buf2, parseConfig, configJson, progress);
1193      if (!status) {
1194        return { status: false, msg: msg };
1195      }
1196    }
1197    return null;
1198  } else {
1199    return null;
1200  }
1201}
1202async function spSystemTraceInitUrl(
1203  sp: SpSystemTrace,
1204  param: { buf?: ArrayBuffer; url?: string },
1205  wasmConfigUri: string,
1206  progress: Function
1207): Promise<{
1208  status: boolean;
1209  msg: string;
1210} | null> {
1211  if (param.url) {
1212    let { status, msg } = await threadPool.initServer(param.url, progress);
1213    if (!status) {
1214      return { status: false, msg: msg };
1215    } else {
1216      return null;
1217    }
1218  } else {
1219    return null;
1220  }
1221}
1222export async function spSystemTraceInit(
1223  sp: SpSystemTrace,
1224  param: { buf?: ArrayBuffer; url?: string; buf2?: ArrayBuffer; fileName1?: string; fileName2?: string },
1225  wasmConfigUri: string,
1226  progress: Function,
1227  isDistributed: boolean
1228): Promise<unknown> {
1229  progress('Load database', 6);
1230  sp.rowsPaneEL!.scroll({ top: 0, left: 0 });
1231  let rsBuf = await spSystemTraceInitBuffer(sp, param, wasmConfigUri, progress);
1232  if (rsBuf) {
1233    return rsBuf;
1234  }
1235  let rsUrl = await spSystemTraceInitUrl(sp, param, wasmConfigUri, progress);
1236  if (rsUrl) {
1237    return rsUrl;
1238  }
1239  if (isDistributed) {
1240    await sp.chartManager?.initDistributedChart(progress, param.fileName1 || 'Trace 1', param.fileName2 || 'Trace 2');
1241  } else {
1242    await sp.chartManager?.init(progress);
1243  }
1244  let rowId: string = '';
1245  // @ts-ignore
1246  sp.rowsEL?.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it) => {
1247    if (it.name.includes('Ark Ts')) {
1248      rowId = it.rowId!;
1249    }
1250    if (it.folder) {
1251      it.addEventListener('expansion-change', sp.extracted(it));
1252    }
1253  });
1254  progress('completed', 100);
1255  info('All TraceRow Data initialized');
1256  sp.loadTraceCompleted = true;
1257  // @ts-ignore
1258  sp.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it) => {
1259    if (rowId !== '' && (it.rowId?.includes(rowId) || it.name.includes(rowId))) {
1260      it.addTemplateTypes('Ark Ts');
1261      for (let child of it.childrenList) {
1262        child.addTemplateTypes('Ark Ts');
1263      }
1264    }
1265    if (it.folder) {
1266      let offsetYTimeOut: unknown = undefined;
1267      it.addEventListener('expansion-change', expansionChangeHandler(sp, offsetYTimeOut));
1268    }
1269    if (sp.loadTraceCompleted) {
1270      sp.traceSheetEL?.displaySystemLogsData();
1271      sp.traceSheetEL?.displayHangsData();
1272      sp.traceSheetEL?.displaySystemStatesData();
1273    }
1274    // 如果有render_service进程,查询该进程下对应泳道的方法存起来,以便框选时直接使用
1275    if (it.getAttribute('name')?.includes('render_service') && it.getAttribute('row-type') === 'process') {
1276      queryRowsData(sp, it.childrenList);
1277    }
1278    sp.intersectionObserver?.observe(it);
1279  });
1280
1281  for (let i = 0; i < pluginArray.length; i++) {
1282    let item = pluginArray[i];
1283    for (let j = 0; j < item.tables.length; j++) {
1284      let tableItem = item.tables[j];
1285      let res = await queryPlugins(tableItem) || [];
1286      if (res.length > 0) {
1287        SpStatisticsHttpUtil.recordPlugin.push(item.pluginName);
1288        break;
1289      } else {
1290        continue;
1291      }
1292    }
1293  }
1294
1295  // 统计插件
1296  SpStatisticsHttpUtil.recordPluginUsage();
1297  // trace文件加载完毕,将动效json文件读取并存入缓存
1298  let funDetailUrl = `https://${window.location.host.split(':')[0]}:${window.location.port
1299    }/application/doc/funDetail.json`;
1300  let xhr = new XMLHttpRequest();
1301  // 创建XMLHttpRequest对象
1302  xhr.open('GET', funDetailUrl);
1303  xhr.onreadystatechange = function (): void {
1304    if (xhr.readyState === 4 && xhr.status === 200) {
1305      let content = xhr.responseText;
1306      caches.open('/funDetail').then((cache) => {
1307        let headers = new Headers();
1308        headers.append('Content-Type', 'application/json');
1309        return cache
1310          .put(
1311            '/funDetail',
1312            new Response(content, {
1313              status: 200,
1314              headers,
1315            })
1316          )
1317          .then();
1318      });
1319    }
1320  };
1321  xhr.send(); // 发送请求
1322  return { status: true, msg: 'success' };
1323}
1324function expansionChangeHandler(sp: SpSystemTrace, offsetYTimeOut: unknown): (event: unknown) => void {
1325  return function (event: unknown) {
1326    sp.scrollH = sp.rowsPaneEL!.scrollHeight;
1327    let max = [...sp.rowsPaneEL!.querySelectorAll('trace-row')].reduce((pre, cur) => pre + cur.clientHeight!, 0);
1328    let offset = sp.rowsPaneEL!.scrollHeight - max;
1329    sp.rowsPaneEL!.scrollTop = sp.rowsPaneEL!.scrollTop - offset;
1330    JankStruct.delJankLineFlag = false;
1331    if (offsetYTimeOut) {
1332      // @ts-ignore
1333      clearTimeout(offsetYTimeOut);
1334    }
1335    // @ts-ignore
1336    if (event.detail.expansion) {
1337      offsetYTimeOut = setTimeout(() => {
1338        sp.linkNodes.forEach((linkNode) => {
1339          JankStruct.selectJankStructList?.forEach((selectStruct: unknown) => {
1340            // @ts-ignore
1341            if (event.detail.rowId === selectStruct.pid) {
1342              // @ts-ignore
1343              JankStruct.selectJankStruct = selectStruct;
1344              // @ts-ignore
1345              JankStruct.hoverJankStruct = selectStruct;
1346            }
1347          });
1348          linkNodeHandler(linkNode, sp);
1349        });
1350      }, 300);
1351    } else {
1352      if (JankStruct!.selectJankStruct) {
1353        JankStruct.selectJankStructList?.push(<JankStruct>JankStruct!.selectJankStruct);
1354      }
1355      offsetYTimeOut = setTimeout(() => {
1356        sp.linkNodes?.forEach((linkNode) => linkNodeHandler(linkNode, sp));
1357      }, 300);
1358    }
1359    let refreshTimeOut = setTimeout(() => {
1360      sp.refreshCanvas(true);
1361      clearTimeout(refreshTimeOut);
1362    }, 360);
1363  };
1364}
1365// 查询render_service对应方法行的所有数据
1366// @ts-ignore
1367function queryRowsData(sp: SpSystemTrace, rowList: Array<TraceRow<unknown>>): void {
1368  rowList.forEach((row): void => {
1369    if (row.getAttribute('row-type') === 'func') {
1370      if (row.getAttribute('name')?.startsWith('render_service')) {
1371        saveFrameRateData(sp, row, 'H:RSMainThread::DoComposition');
1372      } else if (row.getAttribute('name')?.startsWith('RSHardwareThrea')) {
1373        saveFrameRateData(sp, row, 'H:Repaint');
1374      } else if (row.getAttribute('name')?.startsWith('Present')) {
1375        savePresentData(sp, row, 'H:Waiting for Present Fence');
1376      }
1377    }
1378  });
1379}
1380
1381// 查到所有的数据存储起来
1382// @ts-ignore
1383function saveFrameRateData(sp: SpSystemTrace, row: TraceRow<unknown>, funcName: string): void {
1384  let dataList: unknown = [];
1385  queryFuncRowData(funcName, Number(row?.getAttribute('row-id'))).then((res): void => {
1386    if (res.length) {
1387      res.forEach((item): void => {
1388        // @ts-ignore
1389        dataList?.push({ startTime: item.startTime!, tid: item.tid });
1390      });
1391      if (funcName === 'H:RSMainThread::DoComposition') {
1392        // @ts-ignore
1393        sp.docomList = dataList;
1394      } else {
1395        // @ts-ignore
1396        sp.repaintList = dataList;
1397      }
1398    }
1399  });
1400}
1401// 查到present泳道所有的数据存储起来
1402// @ts-ignore
1403function savePresentData(sp: SpSystemTrace, row: TraceRow<unknown>, funcName: string): void {
1404  let dataList: unknown = [];
1405  fuzzyQueryFuncRowData(funcName, Number(row?.getAttribute('row-id'))).then((res): void => {
1406    if (res.length) {
1407      res.forEach((item): void => {
1408        // @ts-ignore
1409        dataList?.push({ endTime: item.endTime!, tid: item.tid });
1410      }); // @ts-ignore
1411      sp.presentList = dataList;
1412    }
1413  });
1414}
1415function linkNodeHandler(linkNode: PairPoint[], sp: SpSystemTrace): void {
1416  if (linkNode[0].rowEL.collect) {
1417    linkNode[0].rowEL.translateY = linkNode[0].rowEL.getBoundingClientRect().top - 195;
1418  } else {
1419    linkNode[0].rowEL.translateY = linkNode[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
1420  }
1421  linkNode[0].y = linkNode[0].rowEL!.translateY! + linkNode[0].offsetY;
1422  if (linkNode[1].rowEL.collect) {
1423    linkNode[1].rowEL.translateY = linkNode[1].rowEL.getBoundingClientRect().top - 195;
1424  } else {
1425    linkNode[1].rowEL.translateY = linkNode[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
1426  }
1427  linkNode[1].y = linkNode[1].rowEL!.translateY! + linkNode[1].offsetY;
1428}
1429
1430const eventMap = {
1431  'cpu-data': 'Cpu',
1432  'cpu-state': 'Cpu State',
1433  'cpu-freq': 'Cpu Frequency',
1434  'cpu-limit-freq': 'Cpu Freq Limit',
1435  process: 'Process',
1436  'native-memory': 'Native Memory',
1437  thread: 'Thread',
1438  func: 'Func',
1439  mem: 'Memory',
1440  'virtual-memory-cell': 'Virtual Memory',
1441  'virtual-memory-group': 'Virtual Memory',
1442  fps: 'FPS',
1443  'ability-monitor': 'Ability Monitor',
1444  'cpu-ability': 'Cpu Ability',
1445  'memory-ability': 'Memory Ability',
1446  'disk-ability': 'DiskIO Ability',
1447  'network-ability': 'Network Ability',
1448  sdk: 'Sdk',
1449  'sdk-counter': 'SDK Counter',
1450  'sdk-slice': 'Sdk Slice',
1451  energy: 'Energy',
1452  'power-energy': 'Power Event',
1453  'system-energy': 'System Event',
1454  'anomaly-energy': 'Anomaly Event',
1455  'clock-group': 'Clocks',
1456  clock: 'clock',
1457  'irq-group': 'Irqs',
1458  irq: 'irq',
1459  hiperf: 'HiPerf (All)',
1460  'hiperf-event': 'HiPerf Event',
1461  'hiperf-report': 'HiPerf Report',
1462  'hiperf-process': 'HiPerf Process',
1463  'hiperf-thread': 'HiPerf Thread',
1464  'js-memory': 'Js Memory',
1465};
1466export function spSystemTraceInitPointToEvent(sp: SpSystemTrace): void {
1467  sp.eventMap = eventMap;
1468}
1469
1470export function spSystemTraceParentRowSticky(sp: SpSystemTrace, deltaY: number): void {
1471  if (deltaY > 0) {
1472    // 从上往下划
1473    const expandRowList = sp.visibleRows.filter((vr) => vr.expansion);
1474    // @ts-ignore
1475    expandRowList.forEach((vr: TraceRow<unknown>) => {
1476      // @ts-ignore
1477      const visibleNotCollectList = vr.childrenList.filter((child: TraceRow<unknown>) => !child.collect && !child.sleeping);
1478      vr.sticky = visibleNotCollectList.length > 0;
1479    });
1480  } else if (deltaY < 0) {
1481    // 从下往上划
1482    sp.visibleRows
1483      .filter((vr) => !vr.folder && vr.parentRowEl && vr.parentRowEl.expansion && !vr.collect)
1484      .forEach((vr) => (vr.parentRowEl!.sticky = true));
1485  } else {
1486    return;
1487  }
1488}
1489