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