• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BaseElement, element } from '../../base-ui/BaseElement';
17import '../../base-ui/popover/LitPopover';
18import '../../base-ui/button/LitButton';
19import { LitMainMenuGroup } from '../../base-ui/menu/LitMainMenuGroup';
20import { LitMainMenuItem } from '../../base-ui/menu/LitMainMenuItem';
21import { SpRecordSetting } from './setting/SpRecordSetting';
22import { LitMainMenu, MenuGroup, MenuItem } from '../../base-ui/menu/LitMainMenu';
23import { SpProbesConfig } from './setting/SpProbesConfig';
24import { SpTraceCommand } from './setting/SpTraceCommand';
25import { HdcStream } from '../../hdc/hdcclient/HdcStream';
26import { FlagsConfig } from './SpFlags';
27import LitSwitch from '../../base-ui/switch/lit-switch';
28import { LitSlider } from '../../base-ui/slider/LitSlider';
29
30import { CreateSessionRequest } from './setting/bean/ProfilerServiceTypes';
31import { PluginConvertUtils } from './setting/utils/PluginConvertUtils';
32import { SpAllocations } from './setting/SpAllocations';
33import { SpRecordPerf } from './setting/SpRecordPerf';
34import { HdcDeviceManager } from '../../hdc/HdcDeviceManager';
35import { LitButton } from '../../base-ui/button/LitButton';
36import { SpApplication } from '../SpApplication';
37import { LitSearch } from './trace/search/Search';
38import { LitProgressBar } from '../../base-ui/progress-bar/LitProgressBar';
39import { log } from '../../log/Log';
40import { CmdConstant } from '../../command/CmdConstant';
41import { Cmd } from '../../command/Cmd';
42import { SpFileSystem } from './setting/SpFileSystem';
43import { SpSdkConfig } from './setting/SpSdkConfig';
44import { SpVmTracker } from './setting/SpVmTracker';
45import { SpHisysEvent } from './setting/SpHisysEvent';
46import { SpRecordTemplate } from './setting/SpRecordTemplate';
47import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil';
48import { SpArkTs } from './setting/SpArkTs';
49import { SpWebHdcShell } from './setting/SpWebHdcShell';
50import { SpHilogRecord } from './setting/SpHilogRecord';
51import { SpXPowerRecord } from './setting/SpXPowerRecord';
52import { LongTraceDBUtils } from '../database/LongTraceDBUtils';
53import {
54  createFpsPluginConfig,
55  createHTracePluginConfig,
56  createHiPerfConfig,
57  createMemoryPluginConfig,
58  createMonitorPlugin,
59  createNativePluginConfig,
60  createSessionRequest,
61  createSystemConfig,
62  createSdkConfig,
63  createHiSystemEventPluginConfig,
64  createArkTsConfig,
65  createHiLogConfig, createFFRTPluginConfig,
66  createXPowerConfig,
67} from './SpRecordConfigModel';
68import { SpRecordTraceHtml } from './SpRecordTrace.html';
69import { SpFFRTConfig } from './setting/SpFFRTConfig';
70import { ShadowRootInput } from './trace/base/ShadowRootInput';
71import { WebSocketManager } from '../../webSocket/WebSocketManager';
72import { TypeConstants } from '../../webSocket/Constants';
73import { LitCheckBox } from '../../base-ui/checkbox/LitCheckBox';
74const DEVICE_NOT_CONNECT =
75  '<div>1.请确认抓取设备上是否已勾选并确认总是允许smartPerf-Host调试的弹窗</div>' +
76  '<div>2.请关闭DevEco Studio,DevEco Testing等会占用hdc端口的应用</div>' +
77  '<div>3.请使用系统管理员权限打开cmd窗口,并执行hdc kill,确保PC端任务管理器中没有hdc进程</div>' +
78  '<div>4.若没有效果,请重新插拔一下手机。紧急情况可拷贝trace命令,在cmd窗口离线抓取</div>';
79
80@element('sp-record-trace')
81export class SpRecordTrace extends BaseElement {
82  public static serialNumber: string = '';
83  public static selectVersion: string | null;
84  public static isVscode = false;
85  public static cancelRecord = false;
86  static supportVersions = ['3.2', '4.0+', '5.0+'];
87  public deviceSelect: HTMLSelectElement | undefined;
88  public deviceVersion: HTMLSelectElement | undefined;
89  private _menuItems: Array<MenuItem> | undefined;
90  private recordButtonText: HTMLSpanElement | undefined;
91  private devicePrompt: HTMLSpanElement | undefined;
92  private recordButton: LitButton | undefined;
93  private cancelButton: LitButton | undefined;
94  private sp: SpApplication | undefined;
95  private progressEL: LitProgressBar | undefined;
96  private litSearch: LitSearch | undefined;
97  private addButton: LitButton | undefined | null;
98  private disconnectButton: LitButton | undefined | null;
99  private recordSetting: SpRecordSetting | undefined;
100  private probesConfig: SpProbesConfig | undefined;
101  private traceCommand: SpTraceCommand | undefined;
102  private spAllocations: SpAllocations | undefined;
103  private spRecordPerf: SpRecordPerf | undefined;
104  private spFileSystem: SpFileSystem | undefined;
105  private spSdkConfig: SpSdkConfig | undefined;
106  private spVmTracker: SpVmTracker | undefined;
107  private spHiSysEvent: SpHisysEvent | undefined;
108  private spRecordTemplate: SpRecordTemplate | undefined;
109  private spArkTs: SpArkTs | undefined;
110  private spHiLog: SpHilogRecord | undefined;
111  private spXPower: SpXPowerRecord | undefined;
112  private spFFRTConfig: SpFFRTConfig | undefined;
113  private ftraceSlider: LitSlider | undefined | null;
114  private spWebShell: SpWebHdcShell | undefined;
115  private menuGroup: LitMainMenuGroup | undefined | null;
116  private appContent: HTMLElement | undefined | null;
117  private record = 'Record';
118  private stop = 'StopRecord';
119  private nowChildItem: HTMLElement | undefined;
120  private longTraceList: Array<string> = [];
121  private refreshDeviceTimer: number | undefined;
122  private hintEl: HTMLSpanElement | undefined;
123  private selectedTemplate: Map<string, number> = new Map();
124  private hintTimeOut: number = -1;
125  private MenuItemArkts: MenuItem | undefined | null;
126  private MenuItemArktsHtml: LitMainMenuItem | undefined | null;
127  private hdcList: Array<unknown> = [];
128  public useExtendCheck: LitCheckBox | undefined | null;
129  public static useExtend = false;
130  private useExtentTip: HTMLElement | undefined | null;
131  private usbSerialNum: Array<string> = [];
132  public static allProcessListStr: string;
133  public static usbGetCpuCount: string;
134  public static usbGetEvent: string;
135  public static usbGetApp: string;
136  private static usbGetVersion: string;
137  static snapShotList: Array<unknown> = [];
138  static snapShotDuration: number = 0;
139
140  set record_template(re: string) {
141    if (re === 'true') {
142      this.setAttribute('record_template', 'true');
143    } else {
144      this.setAttribute('record_template', 'false');
145    }
146    if (this.recordSetting) {
147      this.recordSetting.isRecordTemplate = re === 'true' ? true : false;
148    }
149  }
150
151  get record_template(): string {
152    return this.getAttribute('record_template')!;
153  }
154
155  set vs(vs: boolean) {
156    if (vs) {
157      SpRecordTrace.isVscode = true;
158      this.setAttribute('vs', '');
159    } else {
160      SpRecordTrace.isVscode = false;
161      this.removeAttribute('vs');
162    }
163  }
164
165  get vs(): boolean {
166    return this.hasAttribute('vs');
167  }
168
169  private compareArray(devs: Array<string>): boolean {
170    let clearFlag: boolean = false;
171    if (devs.length !== this.deviceSelect!.options.length) {
172      clearFlag = true;
173    } else {
174      let optionArray: string[] = [];
175      for (let index = 0; index < this.deviceSelect!.options.length; index++) {
176        optionArray.push(this.deviceSelect!.options[index].value);
177      }
178      devs.forEach((value): void => {
179        if (optionArray.indexOf(value) === -1) {
180          clearFlag = true;
181        }
182      });
183    }
184    return clearFlag;
185  }
186
187  private async refreshDeviceList(sn?: unknown): Promise<void> {
188    if (this.vs) {
189      this.refreshDeviceListByVs();
190    } else {
191      this.deviceSelect!.innerHTML = '';
192      // @ts-ignore
193      HdcDeviceManager.getDevices().then(async (devs: USBDevice[]) => {
194        if (devs.length === 0) {
195          this.recordButton!.hidden = true;
196          this.disconnectButton!.hidden = true;
197          this.devicePrompt!.innerText = 'Device not connected';
198          this.hintEl!.innerHTML = DEVICE_NOT_CONNECT;
199          if (!this.showHint) {
200            this.showHint = true;
201          }
202        }
203        this.hdcList = devs;
204        let optionNum = 0;
205        for (let len = 0; len < devs.length; len++) {
206          let dev = devs[len];
207          let option = document.createElement('option');
208          option.className = 'select';
209          if (typeof dev.serialNumber === 'string') {
210            optionNum++;
211            option.value = dev.serialNumber;
212            option.textContent = dev!.serialNumber ? dev!.serialNumber!.toString() : 'hdc Device';
213            this.deviceSelect!.appendChild(option);
214            if (dev.serialNumber === sn) {
215              option.selected = true;
216              this.recordButton!.hidden = false;
217              this.disconnectButton!.hidden = false;
218              this.showHint = false;
219              this.devicePrompt!.innerText = '';
220              this.hintEl!.textContent = '';
221              SpRecordTrace.serialNumber = option.value;
222              this.refreshDeviceVersion(option);
223            }
224          }
225        }
226        if (!optionNum) {
227          this.deviceSelect!.style!.border = '2px solid red';
228          setTimeout(() => {
229            this.deviceSelect!.style!.border = '1px solid #4D4D4D';
230          }, 3000);
231          this.recordButton!.hidden = true;
232          this.disconnectButton!.hidden = true;
233          this.devicePrompt!.innerText = 'Device not connected';
234          this.hintEl!.innerHTML = DEVICE_NOT_CONNECT;
235          if (!this.showHint) {
236            this.showHint = true;
237          }
238        }
239      });
240    }
241  }
242  private refreshDeviceVersion(option: HTMLOptionElement): void {
243    HdcDeviceManager.connect(option.value).then(async (result) => {
244      if (result) {
245        if (this.MenuItemArkts && this.MenuItemArktsHtml) {//连接成功后,arkts开关置灰不能点击
246          this.MenuItemArktsHtml.style.color = 'gray';
247          this.MenuItemArktsHtml.disabled = true;
248          if (this.MenuItemArkts.clickHandler) {
249            this.MenuItemArkts.clickHandler = undefined;
250          }
251        }
252        HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_VERSION, false).then((version) => {
253          SpRecordTrace.selectVersion = this.getDeviceVersion(version);
254          this.setDeviceVersionSelect(SpRecordTrace.selectVersion);
255          this.nativeMemoryHideBySelectVersion();
256          this.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd(
257            PluginConvertUtils.BeanToCmdTxt(this.makeRequest(), false),
258            this.recordSetting!.output,
259            this.recordSetting!.maxDur
260          );
261          if (this.nowChildItem === this.spWebShell) {
262            window.publish(window.SmartEvent.UI.DeviceConnect, option.value);
263          }
264        });
265      } else {
266        SpRecordTrace.selectVersion = SpRecordTrace.supportVersions[0];
267        this.setDeviceVersionSelect(SpRecordTrace.selectVersion);
268        this.nativeMemoryHideBySelectVersion();
269        let cmdTxt = PluginConvertUtils.BeanToCmdTxt(this.makeRequest(), false);
270        this.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd(
271          cmdTxt,
272          this.recordSetting!.output,
273          this.recordSetting!.maxDur
274        );
275      }
276    });
277  }
278  private refreshDeviceListByVs(): void {
279    Cmd.execHdcCmd(CmdConstant.CMD_HDC_DEVICES, (res: string) => {
280      let devs: string[] = res.trim().replace(/\r\n/g, '\r').replace(/\n/g, '\r').split(/\r/);
281      if (devs.length === 1 && devs[0].indexOf('Empty') !== -1) {
282        this.deviceSelect!.innerHTML = '';
283        return;
284      }
285      let clearFlag = this.compareArray(devs);
286      if (clearFlag) {
287        this.deviceSelect!.innerHTML = '';
288        if (devs.length === 0) {
289          this.recordButton!.hidden = true;
290          this.disconnectButton!.hidden = true;
291          this.devicePrompt!.innerText = 'Device not connected';
292        }
293        for (let i = 0; i < devs.length; i++) {
294          let dev = devs[i];
295          let option = document.createElement('option');
296          option.className = 'select';
297          option.textContent = dev;
298          this.deviceSelect!.appendChild(option);
299          if (i === 0) {
300            option.selected = true;
301            this.recordButton!.hidden = false;
302            this.disconnectButton!.hidden = false;
303            SpRecordTrace.serialNumber = option.value;
304            this.devicePrompt!.innerText = '';
305          }
306        }
307      }
308    });
309  }
310
311  private getDeviceVersion(version: string): string {
312    if (version.indexOf('3.2') !== -1) {
313      return '3.2';
314    } else if (version.indexOf('4.') !== -1) {
315      return '4.0+';
316    } else if (version.indexOf('5.') !== -1) {
317      return '5.0+';
318    }
319    return '3.2';
320  }
321
322  private freshMenuDisable(disable: boolean): void {
323    let mainMenu = this.sp!.shadowRoot?.querySelector('#main-menu') as LitMainMenu;
324    mainMenu.menus?.forEach((men): void => {
325      // @ts-ignore
326      men.children.forEach((child: HTMLElement): void => {
327        // @ts-ignore
328        child.disabled = disable;
329      });
330    });
331    mainMenu.menus = mainMenu.menus;
332  }
333
334  refreshConfig(isTraceConfig: boolean): void {
335    let recordSettingEl = this.shadowRoot?.querySelector('record-setting') as SpRecordSetting;
336    if (recordSettingEl) {
337      if (isTraceConfig) {
338        recordSettingEl.setAttribute('trace_config', '');
339      } else {
340        if (recordSettingEl.hasAttribute('trace_config')) {
341          recordSettingEl.removeAttribute('trace_config');
342        }
343      }
344    }
345  }
346
347  refreshHint(): void {
348    let flags = FlagsConfig.getAllFlagConfig();
349    let showHint = false;
350    for (let i = 0; i < flags.length; i++) {
351      let flag = flags[i];
352      if (this.selectedTemplate.has(flag.title)) {
353        let selectedOption = flag.switchOptions.filter((option) => {
354          return option.selected;
355        });
356        if (selectedOption[0].option === 'Disabled') {
357          showHint = true;
358          break;
359        }
360      }
361    }
362    this.showHint = showHint;
363  }
364
365  get showHint(): boolean {
366    return this.hasAttribute('show_hint');
367  }
368
369  set showHint(bool: boolean) {
370    if (bool) {
371      if (this.hasAttribute('show_hint')) {
372        this.removeAttribute('show_hint');
373        this.hintTimeOut = window.setTimeout(() => {
374          this.setAttribute('show_hint', '');
375        }, timeOut);
376      } else {
377        this.setAttribute('show_hint', '');
378      }
379    } else {
380      if (this.hintTimeOut !== -1) {
381        window.clearTimeout(this.hintTimeOut);
382        this.hintTimeOut = -1;
383      }
384      this.removeAttribute('show_hint');
385    }
386  }
387
388  initElements(): void {
389    let parentElement = this.parentNode as HTMLElement;
390    if (parentElement) {
391      parentElement.style.overflow = 'hidden';
392    }
393    this.sp = document.querySelector('sp-application') as SpApplication;
394    if (!this.shadowRoot || !this.sp) {
395      return;
396    }
397    this.initConfigPage();
398    this.hintEl = this.shadowRoot.querySelector('#hint') as HTMLSpanElement;
399    this.deviceSelect = this.shadowRoot.querySelector('#device-select') as HTMLSelectElement;
400    this.deviceVersion = this.shadowRoot.querySelector('#device-version') as HTMLSelectElement;
401    this.devicePrompt = this.shadowRoot.querySelector('.prompt') as HTMLSpanElement;
402    this.disconnectButton = this.shadowRoot.querySelector<LitButton>('.disconnect');
403    this.recordButton = this.shadowRoot.querySelector('.record') as LitButton;
404    this.recordButtonText = this.shadowRoot.querySelector('.record_text') as HTMLSpanElement;
405    this.cancelButton = this.shadowRoot.querySelector('.cancel') as LitButton;
406    this.progressEL = this.sp.shadowRoot?.querySelector('.progress') as LitProgressBar;
407    this.litSearch = this.sp.shadowRoot?.querySelector('#lit-record-search') as LitSearch;
408    this.menuGroup = this.shadowRoot.querySelector('#menu-group') as LitMainMenuGroup;
409    this.addButton = this.shadowRoot.querySelector<LitButton>('.add');
410    if (this.record_template === 'true') {
411      this.buildTemplateTraceItem();
412    } else {
413      this.buildNormalTraceItem();
414    }
415    this.initMenuItems();
416    this.appendDeviceVersion();
417    if (this.deviceSelect.options && this.deviceSelect.options.length > 0) {
418      this.disconnectButton!.hidden = false;
419      this.recordButton.hidden = false;
420      this.devicePrompt.innerText = '';
421    } else {
422      this.disconnectButton!.hidden = true;
423      this.recordButton.hidden = true;
424      this.devicePrompt.innerText = 'Device not connected';
425    }
426    this.useExtendCheck = this.shadowRoot?.querySelector('#use-extend-check') as LitCheckBox;
427    this.useExtentTip = this.shadowRoot?.querySelector('#record_tip') as HTMLElement;
428    this.useExtendCheck?.addEventListener('change', (ev): void => {
429      // @ts-ignore
430      let detail = ev.detail;
431      SpRecordTrace.useExtend = detail.checked;
432      this.initMenuItems();
433      this.buildNormalTraceItem();
434      this.usbSerialNum = [];
435      SpRecordTrace.serialNumber = '';
436      this.recordButton!.hidden = true;
437      this.disconnectButton!.hidden = true;
438      // @ts-ignore
439      while (this.deviceSelect!.firstChild) {
440        this.deviceSelect!.removeChild(this.deviceSelect!.firstChild); // 删除子节点
441      }
442      this.devicePrompt!.innerText = 'Device not connected';
443      if (!detail.checked) {
444        this.spArkTs!.litSwitch!.checked = false;
445        this.spArkTs!.memoryDisable();
446        this.spArkTs!.disable();
447        this.useExtentTip!.style.display = 'none';
448        this.useExtentTip!.innerHTML = '';
449      }
450    });
451    this.spArkTs?.addEventListener('showTip', () => {
452      this.isShowTipFunc('Ark Ts', this.spArkTs!.isStartArkts);
453    });
454    this.recordSetting?.addEventListener('showTip', (event) => {// @ts-ignore
455      this.isShowTipFunc(event.detail.value, event.detail.isShow);
456    });
457  }
458
459  isShowTipFunc(text: string, isShow: boolean): void {
460    if (isShow) {
461      let guideSrc = `https://${window.location.host.split(':')[0]}:${window.location.port}/application/?action=help_27`;
462      this.useExtentTip!.style.display = 'block';
463      // @ts-ignore
464      this.useExtentTip!.innerHTML = `若要抓取${text},请勾选 Use local hdc 开关,启动后台扩展服务进行抓取,相关指导: [</span style="cursor: pointer;"><a href=${guideSrc} style="color: blue;" target="_blank">指导</a><span>]`;
465    } else {
466      this.useExtentTip!.style.display = 'none';
467      this.useExtentTip!.innerHTML = '';
468    }
469  }
470
471  connectedCallback(): void {
472    super.connectedCallback();
473    this.addButton!.addEventListener('click', this.addButtonClickEvent);
474    this.deviceSelect!.addEventListener('mousedown', this.deviceSelectMouseDownEvent);
475    this.deviceSelect!.addEventListener('change', this.deviceSelectChangeEvent);
476    this.deviceVersion!.addEventListener('change', this.deviceVersionChangeEvent);
477    this.disconnectButton?.addEventListener('click', this.disconnectButtonClickEvent);
478    this.recordButton?.addEventListener('mousedown', this.recordButtonMouseDownEvent);
479    this.cancelButton?.addEventListener('click', this.cancelRecordListener);
480    this.spRecordPerf?.addEventListener('addProbe', this.recordAddProbeEvent);
481    this.spAllocations?.addEventListener('addProbe', this.recordAddProbeEvent);
482    this.probesConfig?.addEventListener('addProbe', this.recordAddProbeEvent);
483    this.spRecordTemplate?.addEventListener('addProbe', this.recordTempAddProbe);
484    this.spRecordTemplate?.addEventListener('delProbe', this.recordTempDelProbe);
485  }
486
487  disconnectedCallback(): void {
488    super.disconnectedCallback();
489    this.addButton!.removeEventListener('click', this.addButtonClickEvent);
490    this.deviceSelect!.removeEventListener('mousedown', this.deviceSelectMouseDownEvent);
491    this.deviceSelect!.removeEventListener('change', this.deviceSelectChangeEvent);
492    this.deviceVersion!.removeEventListener('change', this.deviceVersionChangeEvent);
493    this.disconnectButton?.removeEventListener('click', this.disconnectButtonClickEvent);
494    this.recordButton?.removeEventListener('mousedown', this.recordButtonMouseDownEvent);
495    this.cancelButton?.removeEventListener('click', this.cancelRecordListener);
496    this.spRecordPerf?.removeEventListener('addProbe', this.recordAddProbeEvent);
497    this.spAllocations?.removeEventListener('addProbe', this.recordAddProbeEvent);
498    this.probesConfig?.removeEventListener('addProbe', this.recordAddProbeEvent);
499    this.spRecordTemplate?.removeEventListener('addProbe', this.recordTempAddProbe);
500    this.spRecordTemplate?.removeEventListener('delProbe', this.recordTempDelProbe);
501  }
502
503  recordPluginFunc = (): void => {
504    this.useExtentTip!.style.display = 'none';
505    this.useExtentTip!.innerHTML = '';
506
507    this.sp!.search = true;
508    this.progressEL!.loading = true;
509    this.litSearch!.setPercent('Waiting to record...', -1);
510    this.initRecordCmdStatus();
511    let request = this.makeRequest(false);
512    let htraceCmd = PluginConvertUtils.createHdcCmd(
513      PluginConvertUtils.BeanToCmdTxt(request, false),
514      this.recordSetting!.output,
515      this.recordSetting!.maxDur
516    );
517
518    let encoder = new TextEncoder();
519    let processName = this.spArkTs!.process.trim();
520    let isRecordArkTs = (this.spArkTs!.isStartArkts && processName !== '') ? true : false; //是否抓取arkts trace
521    let isRecordHitrace = request.pluginConfigs.length > 0 ? true : false; // 是否抓取其他模块 hitrace
522
523    let isStartCpuProfiler = this.spArkTs!.isStartCpuProfiler; //cpu Profiler 开关是否打开
524    let isStartMemoryProfiler = this.spArkTs!.isStartMemoryProfiler; //memory Profiler 开关是否打开
525    let isCheckSnapshot = this.spArkTs!.radioBoxType === 0 ? true : false; // 是否check snapshot
526    let isCheckTimeLine = this.spArkTs!.radioBoxType === 1 ? true : false; // 是否 check timeline
527
528    let maxDur = this.recordSetting!.maxDur; // 抓取trace的时长
529    let snapShotDur = this.recordSetting!.snapShot;//截图
530    SpRecordTrace.snapShotDuration = snapShotDur;
531    let snapshotTimeInterval = this.spArkTs!.intervalValue;
532    let cpuProfTimeInt = this.spArkTs!.intervalCpuValue;
533    let captureNumericValue = this.spArkTs!.grabNumeric; // snapshot check box
534    let trackAllocations = this.spArkTs!.grabAllocations; // timeline check box
535    let enableCpuProfiler = this.spArkTs!.isStartCpuProfiler;
536
537    let params: unknown = {
538      isRecordArkTs: isRecordArkTs,
539      isRecordHitrace: isRecordHitrace,
540      type: '',
541      processName: processName,
542      maxDur: maxDur,
543      snapShotDur: snapShotDur,
544      snapshotTimeInterval: snapshotTimeInterval,
545      cpuProfilerInterval: cpuProfTimeInt,
546      captureNumericValue: captureNumericValue,
547      trackAllocations: trackAllocations,
548      enableCpuProfiler: enableCpuProfiler,
549      htraceCmd: htraceCmd,
550      output: this.recordSetting!.output,
551      serialNum: SpRecordTrace.serialNumber
552    };
553
554    if (isStartCpuProfiler && !isStartMemoryProfiler) { // @ts-ignore
555      params.type = 'cpuProf';
556    } else if (!isStartCpuProfiler && isStartMemoryProfiler && isCheckSnapshot) {// @ts-ignore
557      params.type = 'snapshot';
558    } else if (!isStartCpuProfiler && isStartMemoryProfiler && isCheckTimeLine) {// @ts-ignore
559      params.type = 'timeline';
560    } else if (isStartCpuProfiler && isStartMemoryProfiler && isCheckSnapshot) {// @ts-ignore
561      params.type = 'cpuProf_snapshot';
562    } else if (isStartCpuProfiler && isStartMemoryProfiler && isCheckTimeLine) {// @ts-ignore
563      params.type = 'cpuProf_timeline';
564    }
565
566    let onmessageCallBack = (cmd: number, result: unknown): void => {// @ts-ignore
567      if (cmd === 2 && result.byteLength > 0) {
568        let name = this.recordSetting!.output.split('/').reverse()[0];// @ts-ignore
569        let file = new File([result], name);
570        let main = this!.parentNode!.parentNode!.querySelector('lit-main-menu') as LitMainMenu;
571        let children = main.menus as Array<MenuGroup>;
572        let child = children[0].children as Array<MenuItem>;
573        let fileHandler = child[0].fileHandler;
574        if (fileHandler) {
575          this.refreshDisableStyle(false, false);
576          this.recordButton!.hidden = false;
577          fileHandler({
578            detail: file,
579          });
580        }
581      } else if (cmd === 3) {
582        this.sp!.search = false;
583        this.progressEL!.loading = false;// @ts-ignore
584        let errorMsg = new TextDecoder().decode(result);
585        this.useExtentTip!.style.display = 'block';
586        this.useExtentTip!.innerHTML = errorMsg;
587        this.refreshDisableStyle(false, false);
588        this.recordButton!.hidden = false;
589        this.sp!.search = false;
590        this.progressEL!.loading = false;
591      } else if (cmd === 4) {
592        let aElement = document.createElement('a');// @ts-ignore
593        aElement.href = URL.createObjectURL(new Blob([result!]));
594        aElement.download = 'arkts.htrace';
595        aElement.click();
596      } else if (cmd === 5) {// @ts-ignore
597        SpRecordTrace.snapShotList = JSON.parse(new TextDecoder('utf-8').decode(result)) as string[];
598      } else if (cmd === 6) {
599        this.litSearch!.setPercent('Start to record...', -1);
600      } else if (cmd === 7) {
601        this.litSearch!.setPercent('Tracing htrace down', -1);
602      } else if (cmd === 8) {
603        this.litSearch!.setPercent('Downloading Hitrace file...', -1);
604      }
605    };
606    WebSocketManager.getInstance()!.registerMessageListener(TypeConstants.ARKTS_TYPE, onmessageCallBack, this.eventCallBack);
607    WebSocketManager.getInstance()!.sendMessage(TypeConstants.ARKTS_TYPE, 1, encoder.encode(JSON.stringify(params)));
608  };
609
610  recordTempAddProbe = (ev: CustomEventInit<{ elementId: string }>): void => {
611    if (
612      FlagsConfig.DEFAULT_CONFIG.find((flagItem) => {
613        return flagItem.title === ev.detail!.elementId;
614      })
615    ) {
616      this.selectedTemplate.set(ev.detail!.elementId, 1);
617      let flagConfig = FlagsConfig.getFlagsConfig(ev.detail!.elementId);
618      if (flagConfig![ev.detail!.elementId] !== 'Enabled') {
619        this.hintEl!.textContent = 'Please open the corresponding Flags tag when parsing';
620        if (!this.showHint) {
621          this.showHint = true;
622        }
623      }
624    }
625  };
626
627  recordTempDelProbe = (ev: CustomEventInit<{ elementId: string }>): void => {
628    if (
629      FlagsConfig.DEFAULT_CONFIG.find((flagItem): boolean => {
630        return flagItem.title === ev.detail!.elementId;
631      })
632    ) {
633      this.selectedTemplate.delete(ev.detail!.elementId);
634      if (this.selectedTemplate.size === 0) {
635        this.showHint = false;
636      }
637    }
638  };
639
640  recordAddProbeEvent = (): void => {
641    this.showHint = false;
642  };
643
644  addButtonClickEvent = (event: MouseEvent): void => {
645    if (SpRecordTrace.useExtend) {
646      this.useExtentTip!.innerHTML = '';
647      this.useExtentTip!.style.display = 'none';
648      WebSocketManager.getInstance()!.registerMessageListener(TypeConstants.USB_TYPE, this.webSocketCallBackasync, this.eventCallBack);
649      WebSocketManager.getInstance()!.sendMessage(TypeConstants.USB_TYPE, TypeConstants.USB_SN_CMD);
650    } else if (this.vs) {
651      this.refreshDeviceList();
652    } else {
653      // @ts-ignore
654      HdcDeviceManager.findDevice().then((usbDevices): void => {
655        log(usbDevices);
656        HdcDeviceManager.connect(usbDevices.serialNumber).then((res) => {
657          if (res) {
658            this.refreshDeviceList(usbDevices.serialNumber);
659          } else {
660            this.recordButton!.hidden = true;
661            this.disconnectButton!.hidden = true;
662            this.devicePrompt!.innerText = 'Device not connected';
663            this.hintEl!.innerHTML = DEVICE_NOT_CONNECT;
664            if (!this.showHint) {
665              this.showHint = true;
666            }
667          }
668        });
669      });
670    }
671  };
672
673  eventCallBack = (result: string): void => {
674    this.recordButton!.hidden = true;
675    this.disconnectButton!.hidden = true;
676    this.disconnectButtonClickEvent();
677    this.useExtentTip!.style.display = 'block';
678    // @ts-ignore
679    this.useExtentTip!.innerHTML = this.getStatusesPrompt()[result].prompt;
680  };
681
682  getStatusesPrompt(): unknown {
683    let guideSrc = `https://${window.location.host.split(':')[0]}:${window.location.port
684      }/application/?action=help_27`;
685    return {
686      unconnected: {
687        prompt: `未连接,请启动本地扩展程序再试![</span style="cursor: pointer;"><a href=${guideSrc} style="color: blue;" target="_blank">指导</a><span>]`
688      }, // 重连
689      connected: {
690        prompt: '扩展程序连接中,请稍后再试'
691      }, // 中间
692      logined: {
693        prompt: '扩展程序连接中,请稍后再试'
694      }, // 中间
695      loginFailedByLackSession: {
696        prompt: '当前所有会话都在使用中,请释放一些会话再试!'
697      }, // 重连
698      upgrading: {
699        prompt: '扩展程序连接中,请稍后再试!'
700      }, // 中间
701      upgradeSuccess: {
702        prompt: '扩展程序已完成升级,重启中,请稍后再试!'
703      }, // 重连
704      upgradeFailed: {
705        prompt: '刷新页面触发升级,或卸载扩展程序重装!'
706      }, // 重连
707    };
708  };
709
710  webSocketCallBackasync = (cmd: number, result: Uint8Array): void => {
711    const decoder = new TextDecoder();
712    const jsonString = decoder.decode(result);
713    let jsonRes = JSON.parse(jsonString);
714    if (cmd === TypeConstants.USB_SN_CMD) {
715      this.hdcList = jsonRes.resultMessage;
716      HdcDeviceManager.findDevice().then((usbDevices): void => {
717        SpRecordTrace.serialNumber = usbDevices.serialNumber;
718        this.usbSerialNum = jsonRes.resultMessage;
719        let optionNum = 0;
720        if (this.usbSerialNum.length === 1 && this.usbSerialNum[0].includes('Empty')) {
721          this.usbSerialNum.shift();
722          this.recordButton!.hidden = true;
723          this.disconnectButton!.hidden = true;
724          this.devicePrompt!.innerText = 'Device not connected';
725          this.deviceSelect!.style!.border = '2px solid red';
726          setTimeout(() => {
727            this.deviceSelect!.style!.border = '1px solid #4D4D4D';
728          }, 3000);
729          this.useExtentTip!.style.display = 'block';
730          this.useExtentTip!.innerHTML = '手机连接有问题,请重新插拔一下手机,或者请使用系统管理员权限打开cmd窗口,并执行hdc shell';
731          return;
732        }
733        // @ts-ignore
734        while (this.deviceSelect!.firstChild) {
735          this.deviceSelect!.removeChild(this.deviceSelect!.firstChild); // 删除子节点
736        }
737        for (let len = 0; len < this.usbSerialNum.length; len++) {
738          let dev = this.usbSerialNum[len];
739          let option = document.createElement('option');
740          option.className = 'select';
741          optionNum++;
742          // @ts-ignore
743          option.value = dev;
744          // @ts-ignore
745          option.textContent = dev.toString();
746          this.deviceSelect!.appendChild(option);
747          if (dev.toString() === SpRecordTrace.serialNumber) {
748            option.selected = true;
749            this.recordButton!.hidden = false;
750            this.disconnectButton!.hidden = false;
751            this.devicePrompt!.innerText = '';
752            this.hintEl!.textContent = '';
753            // @ts-ignore
754            WebSocketManager.getInstance()!.sendMessage(TypeConstants.USB_TYPE, TypeConstants.USB_GET_VERSION, new TextEncoder().encode(dev));
755            setTimeout(() => {
756              if (SpRecordTrace.usbGetVersion) {
757                SpRecordTrace.selectVersion = this.getDeviceVersion(SpRecordTrace.usbGetVersion);
758                this.setDeviceVersionSelect(SpRecordTrace.selectVersion);
759                this.nativeMemoryHideBySelectVersion();
760              }
761            }, 1000);
762          }
763        }
764        if (!optionNum) {
765          this.deviceSelect!.style!.border = '2px solid red';
766          setTimeout(() => {
767            this.deviceSelect!.style!.border = '1px solid #4D4D4D';
768          }, 3000);
769          this.recordButton!.hidden = true;
770          this.disconnectButton!.hidden = true;
771          this.devicePrompt!.innerText = 'Device not connected';
772          this.useExtentTip!.style.display = 'block';
773          this.useExtentTip!.innerHTML = '手机连接有问题,请重新插拔一下手机,或者请使用系统管理员权限打开cmd窗口,并执行hdc shell';
774        }
775      });
776    } else if (cmd === TypeConstants.USB_GET_PROCESS) {
777      // @ts-ignore
778      SpRecordTrace.allProcessListStr = jsonRes.resultMessage;
779    } else if (cmd === TypeConstants.USB_GET_CPU_COUNT) {
780      SpRecordTrace.usbGetCpuCount = jsonRes.resultMessage;
781    } else if (cmd === TypeConstants.USB_GET_EVENT) {
782      SpRecordTrace.usbGetEvent = jsonRes.resultMessage;
783    } else if (cmd === TypeConstants.USB_GET_APP) {
784      SpRecordTrace.usbGetApp = jsonRes.resultMessage;
785    } else if (cmd === TypeConstants.USB_GET_VERSION) {
786      SpRecordTrace.usbGetVersion = jsonRes.resultMessage;
787    }
788  };
789
790  deviceSelectMouseDownEvent = (evt: MouseEvent): void => {
791    if (this.deviceSelect!.options.length === 0) {
792      evt.preventDefault();
793    }
794  };
795
796  deviceSelectChangeEvent = (): void => {
797    if (this.deviceSelect!.options.length > 0) {
798      this.recordButton!.hidden = false;
799      this.disconnectButton!.hidden = false;
800      this.devicePrompt!.innerText = '';
801    } else {
802      this.recordButton!.hidden = true;
803      this.disconnectButton!.hidden = true;
804      this.devicePrompt!.innerText = 'Device not connected';
805    }
806
807    if (SpRecordTrace.useExtend) {
808      let deviceItem = this.deviceSelect!.options[this.deviceSelect!.selectedIndex];
809      let value = deviceItem.value;
810      SpRecordTrace.serialNumber = value;
811      return;
812    }
813
814    let deviceItem = this.deviceSelect!.options[this.deviceSelect!.selectedIndex];
815    let value = deviceItem.value;
816    SpRecordTrace.serialNumber = value;
817    if (this.vs) {
818      let cmd = Cmd.formatString(CmdConstant.CMD_GET_VERSION_DEVICES, [SpRecordTrace.serialNumber]);
819      Cmd.execHdcCmd(cmd, (deviceVersion: string) => {
820        this.selectedDevice(deviceVersion);
821        this.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd(
822          PluginConvertUtils.BeanToCmdTxt(this.makeRequest(), false),
823          this.recordSetting!.output,
824          this.recordSetting!.maxDur
825        );
826      });
827    } else {
828      HdcDeviceManager.connect(value).then((result): void => {
829        if (result) {
830          HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_VERSION, true).then((deviceVersion) => {
831            this.selectedDevice(deviceVersion);
832            this.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd(
833              PluginConvertUtils.BeanToCmdTxt(this.makeRequest(), false),
834              this.recordSetting!.output,
835              this.recordSetting!.maxDur
836            );
837            if (this.nowChildItem === this.spWebShell) {
838              window.publish(window.SmartEvent.UI.DeviceConnect, value);
839            }
840          });
841        } else {
842          SpRecordTrace.selectVersion = SpRecordTrace.supportVersions[0];
843          this.setDeviceVersionSelect(SpRecordTrace.selectVersion);
844          this.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd(
845            PluginConvertUtils.BeanToCmdTxt(this.makeRequest(), false),
846            this.recordSetting!.output,
847            this.recordSetting!.maxDur
848          );
849        }
850      });
851    }
852  };
853
854  deviceVersionChangeEvent = (): void => {
855    let versionItem = this.deviceVersion!.options[this.deviceVersion!.selectedIndex];
856    SpRecordTrace.selectVersion = versionItem.getAttribute('device-version');
857    this.spAllocations!.startup_mode = false;
858    this.spAllocations!.recordJsStack = false;
859    this.nativeMemoryHideBySelectVersion();
860    this.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd(
861      PluginConvertUtils.BeanToCmdTxt(this.makeRequest(), false),
862      this.recordSetting!.output,
863      this.recordSetting!.maxDur
864    );
865  };
866
867  disconnectButtonClickEvent = (): void => {
868    this.setDeviceVersionSelect('5.0+');
869    let index = this.deviceSelect!.selectedIndex;
870    if (index !== -1 && this.deviceSelect!.options.length > 0) {
871      for (let i = 0; i < this.deviceSelect!.options.length; i++) {
872        let selectOption = this.deviceSelect!.options[i];
873        let value = selectOption.value;
874        HdcDeviceManager.disConnect(value).then((): void => {
875          this.deviceSelect!.removeChild(selectOption);
876          if (this.nowChildItem === this.spWebShell) {
877            window.publish(window.SmartEvent.UI.DeviceDisConnect, value);
878          }
879          let options = this.deviceSelect!.options;
880          if (options.length <= 0) {
881            this.recordButton!.hidden = true;
882            this.disconnectButton!.hidden = true;
883            this.devicePrompt!.innerText = 'Device not connected';
884            this.sp!.search = false;
885            SpRecordTrace.serialNumber = '';
886          }
887        });
888      }
889    }
890  };
891
892  recordButtonMouseDownEvent = (event: MouseEvent): void => {
893    if (event.button === 0) {
894      if (this.recordButtonText!.textContent === this.record) {
895        this.recordButtonListener();
896      } else {
897        this.stopRecordListener();
898      }
899    }
900  };
901
902  private initConfigPage(): void {
903    this.recordSetting = new SpRecordSetting();
904    this.probesConfig = new SpProbesConfig();
905    this.traceCommand = new SpTraceCommand();
906    this.spAllocations = new SpAllocations();
907    this.spRecordPerf = new SpRecordPerf();
908    this.spFileSystem = new SpFileSystem();
909    this.spSdkConfig = new SpSdkConfig();
910    this.spVmTracker = new SpVmTracker();
911    this.spHiSysEvent = new SpHisysEvent();
912    this.spArkTs = new SpArkTs();
913    this.spHiLog = new SpHilogRecord();
914    this.spXPower = new SpXPowerRecord();
915    this.spFFRTConfig = new SpFFRTConfig();
916    this.spWebShell = new SpWebHdcShell();
917    this.spRecordTemplate = new SpRecordTemplate(this);
918    this.appContent = this.shadowRoot?.querySelector('#app-content') as HTMLElement;
919    if (this.record_template === 'true') {
920      this.appContent.append(this.spRecordTemplate);
921    } else {
922      this.appContent.append(this.recordSetting);
923    }
924    // @ts-ignore
925    if (navigator.usb) {
926      // @ts-ignore
927      navigator.usb.addEventListener(
928        'disconnect',
929        // @ts-ignore
930        (ev: USBConnectionEvent) => {
931          this.usbDisConnectionListener(ev);
932        }
933      );
934    }
935  }
936
937  reConfigPage(): void {
938    this.appContent = this.shadowRoot?.querySelector('#app-content') as HTMLElement;
939    this.appContent.innerHTML = '';
940    this._menuItems = [];
941    if (this.record_template === 'true') {
942      this.appContent.append(this.spRecordTemplate!);
943      this.buildTemplateTraceItem();
944    } else {
945      this.appContent.append(this.recordSetting!);
946      this.buildNormalTraceItem();
947    }
948    this.initMenuItems();
949  }
950
951  private nativeMemoryHideBySelectVersion(): void {
952    let divConfigs = this.spAllocations?.shadowRoot?.querySelectorAll<HTMLDivElement>('.version-controller');
953    if (divConfigs) {
954      if (SpRecordTrace.selectVersion !== '3.2') {
955        for (let divConfig of divConfigs) {
956          divConfig!.style.zIndex = '1';
957        }
958      } else {
959        for (let divConfig of divConfigs) {
960          divConfig!.style.zIndex = '-1';
961        }
962      }
963    }
964  }
965
966  private selectedDevice(deviceVersion: string): void {
967    SpRecordTrace.selectVersion = this.getDeviceVersion(deviceVersion);
968    this.setDeviceVersionSelect(SpRecordTrace.selectVersion);
969  }
970
971  private appendDeviceVersion(): void {
972    SpRecordTrace.supportVersions.forEach((supportVersion) => {
973      let option = document.createElement('option');
974      option.className = 'select';
975      option.selected = supportVersion === '5.0+';
976      option.textContent = `OpenHarmony-${supportVersion}`;
977      option.setAttribute('device-version', supportVersion);
978      this.deviceVersion!.append(option);
979      SpRecordTrace.selectVersion = '5.0+';
980      this.nativeMemoryHideBySelectVersion();
981    });
982  }
983
984  private setDeviceVersionSelect(selected: string): void {
985    let children = this.deviceVersion!.children;
986    for (let i = 0; i < children.length; i++) {
987      let child = children[i] as HTMLOptionElement;
988      if (child.getAttribute('device-version') === selected) {
989        child.selected = true;
990        break;
991      }
992    }
993  }
994
995  stopRecordListener(): void {
996    this.recordButtonText!.textContent = this.record;
997    this.recordButtonDisable(true);
998    this.cancelButtonShow(false);
999    if (this.vs) {
1000      let cmd = Cmd.formatString(CmdConstant.CMS_HDC_STOP, [SpRecordTrace.serialNumber]);
1001      Cmd.execHdcCmd(cmd, (): void => { });
1002    } else {
1003      let selectedOption = this.deviceSelect!.options[this.deviceSelect!.selectedIndex] as HTMLOptionElement;
1004      HdcDeviceManager.connect(selectedOption.value).then((result) => {
1005        if (result) {
1006          try {
1007            HdcDeviceManager.shellResultAsString(CmdConstant.CMS_STOP, true).then((): void => { });
1008          } catch (exception) {
1009            this.recordButtonDisable(false);
1010            log(exception);
1011          }
1012        }
1013      });
1014    }
1015  }
1016
1017  cancelRecordListener = (): void => {
1018    this.recordButtonText!.textContent = this.record;
1019    this.cancelButtonShow(false);
1020    if (this.vs) {
1021      let cmd = Cmd.formatString(CmdConstant.CMS_HDC_CANCEL, [SpRecordTrace.serialNumber]);
1022      Cmd.execHdcCmd(cmd, () => {
1023        this.freshMenuDisable(false);
1024        this.freshConfigMenuDisable(false);
1025        this.progressEL!.loading = false;
1026        this.sp!.search = false;
1027        this.litSearch!.clear();
1028        this.addButton!.style.pointerEvents = 'auto';
1029        this.deviceSelect!.style.pointerEvents = 'auto';
1030        this.disconnectButton!.style.pointerEvents = 'auto';
1031        this.deviceVersion!.style.pointerEvents = 'auto';
1032      });
1033    } else {
1034      let selectedOption = this.deviceSelect!.options[this.deviceSelect!.selectedIndex] as HTMLOptionElement;
1035      HdcDeviceManager.connect(selectedOption.value).then((result) => {
1036        if (result) {
1037          this.freshMenuDisable(false);
1038          this.freshConfigMenuDisable(false);
1039          try {
1040            this.progressEL!.loading = false;
1041            this.sp!.search = false;
1042            this.litSearch!.clear();
1043            this.disconnectButton!.style.pointerEvents = 'auto';
1044            this.addButton!.style.pointerEvents = 'auto';
1045            this.deviceSelect!.style.pointerEvents = 'auto';
1046            this.deviceVersion!.style.pointerEvents = 'auto';
1047            SpRecordTrace.cancelRecord = true;
1048            HdcDeviceManager.stopHiprofiler(CmdConstant.CMS_CANCEL).then((): void => { });
1049          } catch (exception) {
1050            log(exception);
1051          }
1052        }
1053      });
1054    }
1055  };
1056
1057  private cancelButtonShow(show: boolean): void {
1058    if (show) {
1059      this.cancelButton!.style.visibility = 'visible';
1060    } else {
1061      this.cancelButton!.style.visibility = 'hidden';
1062    }
1063  }
1064
1065  private traceCommandClickHandler(recordTrace: SpRecordTrace): void {
1066    recordTrace.appContent!.innerHTML = '';
1067    recordTrace.appContent!.append(recordTrace.traceCommand!);
1068    recordTrace.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd(
1069      PluginConvertUtils.BeanToCmdTxt(recordTrace.makeRequest(), false),
1070      recordTrace.recordSetting!.output,
1071      recordTrace.recordSetting!.maxDur
1072    );
1073    recordTrace.freshMenuItemsStatus('Trace command');
1074  }
1075
1076  private initMenuItems(): void {
1077    this.menuGroup!.innerHTML = '';
1078    this._menuItems?.forEach((item): void => {
1079      let th = new LitMainMenuItem();
1080      th.setAttribute('icon', item.icon || '');
1081      th.setAttribute('title', item.title || '');
1082      th.style.height = '60px';
1083      th.style.fontFamily = 'Helvetica-Bold';
1084      th.style.fontSize = '16px';
1085      th.style.lineHeight = '28px';
1086      th.style.fontWeight = '700';
1087      th.removeAttribute('file');
1088      th.addEventListener('click', (): void => {
1089        if (item.clickHandler) {
1090          item.clickHandler(item);
1091        }
1092      });
1093      if (item.title === 'eBPF Config') {
1094        if (th && item) {//ebpf开关置灰不能点击
1095          th.style.color = 'gray';
1096          th.disabled = true;
1097          if (item.clickHandler) {
1098            item.clickHandler = undefined;
1099          }
1100        }
1101      }
1102      if (SpRecordTrace.useExtend && item.title === 'Hdc Shell') {
1103        if (th && item) {
1104          th.style.color = 'gray';
1105          th.disabled = true;
1106          if (item.clickHandler) {
1107            item.clickHandler = undefined;
1108          }
1109        }
1110      }
1111      this.menuGroup!.appendChild(th);
1112    });
1113  }
1114
1115  private recordCommandClickHandler(recordTrace: SpRecordTrace): void {
1116    let request = recordTrace.makeRequest();
1117    recordTrace.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd(
1118      PluginConvertUtils.BeanToCmdTxt(request, false),
1119      recordTrace.recordSetting!.output,
1120      recordTrace.recordSetting!.maxDur
1121    );
1122  }
1123
1124  private hdcShellClickHandler(recordTrace: SpRecordTrace): void {
1125    recordTrace.spWebShell!.shellDiv!.scrollTop = recordTrace.spWebShell!.currentScreenRemain;
1126    setTimeout(() => {
1127      recordTrace.spWebShell!.hdcShellFocus();
1128    }, 100);
1129    recordTrace.nowChildItem = recordTrace.spWebShell!;
1130  }
1131
1132  private nativeMemoryClickHandler(recordTrace: SpRecordTrace): void {
1133    let startNativeSwitch = recordTrace.spAllocations?.shadowRoot?.getElementById('switch-disabled') as LitSwitch;
1134    let recordModeSwitch = recordTrace.probesConfig?.shadowRoot?.querySelector('lit-switch') as LitSwitch;
1135    let checkDesBoxDis = recordTrace.probesConfig?.shadowRoot?.querySelectorAll('check-des-box');
1136    let litCheckBoxDis = recordTrace.probesConfig?.shadowRoot?.querySelectorAll('lit-check-box');
1137    recordTrace.ftraceSlider =
1138      recordTrace.probesConfig?.shadowRoot?.querySelector<LitSlider>('#ftrace-buff-size-slider');
1139    startNativeSwitch.addEventListener('change', (event: unknown): void => {
1140      //@ts-ignore
1141      let detail = event.detail;
1142      if (detail!.checked) {
1143        recordModeSwitch.removeAttribute('checked');
1144        checkDesBoxDis?.forEach((item: unknown): void => {
1145          //@ts-ignore
1146          item.setAttribute('disabled', '');
1147          //@ts-ignore
1148          item.checked = false;
1149        });
1150        litCheckBoxDis?.forEach((item: unknown): void => {
1151          //@ts-ignore
1152          item.setAttribute('disabled', '');
1153          //@ts-ignore
1154          item.checked = false;
1155        });
1156        recordTrace.ftraceSlider!.setAttribute('disabled', '');
1157      }
1158    });
1159    let divConfigs = recordTrace.spAllocations?.shadowRoot?.querySelectorAll<HTMLDivElement>('.version-controller');
1160    if ((!SpRecordTrace.selectVersion || SpRecordTrace.selectVersion === '3.2') && divConfigs) {
1161      for (let divConfig of divConfigs) {
1162        divConfig!.style.zIndex = '-1';
1163      }
1164    }
1165  }
1166
1167  private eBPFConfigClickHandler(recordTrace: SpRecordTrace): void {
1168    recordTrace.spFileSystem!.setAttribute('long_trace', '');
1169  }
1170
1171  private buildMenuItem(
1172    title: string,
1173    icon: string,
1174    configPage: BaseElement,
1175    clickHandlerFun?: Function,
1176    fileChoose: boolean = false
1177  ): MenuItem {
1178    return {
1179      title: title,
1180      icon: icon,
1181      fileChoose: fileChoose,
1182      clickHandler: (): void => {
1183        this.appContent!.innerHTML = '';
1184        this.appContent!.append(configPage);
1185        ShadowRootInput.preventBubbling(configPage);
1186        this.freshMenuItemsStatus(title);
1187        if (clickHandlerFun) {
1188          clickHandlerFun(this);
1189        }
1190      },
1191    };
1192  }
1193
1194  private buildTemplateTraceItem(): void {
1195    this._menuItems = [
1196      this.buildMenuItem('Record setting', 'properties', this.recordSetting!),
1197      this.buildMenuItem('Trace template', 'realIntentionBulb', this.spRecordTemplate!),
1198      this.buildMenuItem('Trace command', 'dbsetbreakpoint', this.spRecordTemplate!, this.traceCommandClickHandler),
1199    ];
1200  }
1201
1202  private buildNormalTraceItem(): void {
1203    this._menuItems = [
1204      this.buildMenuItem('Record setting', 'properties', this.recordSetting!),
1205      this.buildMenuItem('Trace command', 'dbsetbreakpoint', this.traceCommand!, this.recordCommandClickHandler),
1206      this.buildMenuItem('Hdc Shell', 'file-config', this.spWebShell!, this.hdcShellClickHandler),
1207      this.buildMenuItem('Probes config', 'realIntentionBulb', this.probesConfig!),
1208      this.buildMenuItem('Native Memory', 'externaltools', this.spAllocations!, this.nativeMemoryClickHandler),
1209      this.buildMenuItem('Hiperf', 'realIntentionBulb', this.spRecordPerf!),
1210      this.buildMenuItem('eBPF Config', 'file-config', this.spFileSystem!, this.eBPFConfigClickHandler),
1211      this.buildMenuItem('VM Tracker', 'vm-tracker', this.spVmTracker!),
1212      this.buildMenuItem('HiSystemEvent', 'externaltools', this.spHiSysEvent!),
1213      this.buildMenuItem('Ark Ts', 'file-config', this.spArkTs!),
1214      this.buildMenuItem('FFRT', 'file-config', this.spFFRTConfig!),
1215      this.buildMenuItem('Hilog', 'realIntentionBulb', this.spHiLog!),
1216      this.buildMenuItem('Xpower', 'externaltools', this.spXPower!),
1217    ];
1218  }
1219
1220  // @ts-ignore
1221  usbDisConnectionListener(event: USBConnectionEvent): void {
1222    // @ts-ignore
1223    let disConnectDevice: USBDevice = event.device;
1224    for (let index = 0; index < this.deviceSelect!.children.length; index++) {
1225      let option = this.deviceSelect!.children[index] as HTMLOptionElement;
1226      if (option.value === disConnectDevice.serialNumber) {
1227        let optValue = option.value;
1228        HdcDeviceManager.disConnect(optValue).then(() => { });
1229        this.deviceSelect!.removeChild(option);
1230        if (SpRecordTrace.serialNumber === optValue) {
1231          if (this.nowChildItem === this.spWebShell) {
1232            window.publish(window.SmartEvent.UI.DeviceDisConnect, optValue);
1233          }
1234          let options = this.deviceSelect!.options;
1235          if (options.length > 0) {
1236            let selectedOpt = options[this.deviceSelect!.selectedIndex];
1237            SpRecordTrace.serialNumber = selectedOpt.value;
1238          } else {
1239            this.recordButton!.hidden = true;
1240            this.disconnectButton!.hidden = true;
1241            this.devicePrompt!.innerText = 'Device not connected';
1242            SpRecordTrace.serialNumber = '';
1243          }
1244        }
1245      }
1246    }
1247  }
1248
1249  private vsCodeRecordCmd(traceCommandStr: string): void {
1250    Cmd.execHdcCmd(Cmd.formatString(CmdConstant.CMS_HDC_STOP, [SpRecordTrace.serialNumber]), (stopRes: string) => {
1251      let cmd = Cmd.formatString(CmdConstant.CMD_MOUNT_DEVICES, [SpRecordTrace.serialNumber]);
1252      Cmd.execHdcCmd(cmd, (res: string) => {
1253        this.sp!.search = true;
1254        this.progressEL!.loading = true;
1255        this.litSearch!.clear();
1256        this.litSearch!.setPercent(`tracing  ${this.recordSetting!.maxDur * 1000}ms`, -1);
1257        this.initRecordUIState();
1258        this.recordButtonText!.textContent = this.stop;
1259        this.cancelButtonShow(true);
1260        Cmd.execHdcTraceCmd(traceCommandStr, SpRecordTrace.serialNumber, (traceResult: string): void => {
1261          if (traceResult.indexOf('DestroySession done') !== -1) {
1262            this.litSearch!.setPercent('tracing htrace down', -1);
1263            let cmd = Cmd.formatString(CmdConstant.CMD_FIEL_RECV_DEVICES, [
1264              SpRecordTrace.serialNumber,
1265              this.recordSetting!.output,
1266            ]);
1267            Cmd.execFileRecv(cmd, this.recordSetting!.output, (rt: ArrayBuffer): void => {
1268              this.litSearch!.setPercent('downloading Hitrace file ', 101);
1269              let fileName = this.recordSetting!.output.substring(this.recordSetting!.output.lastIndexOf('/') + 1);
1270              let file = new File([rt], fileName);
1271              let main = this!.parentNode!.parentNode!.querySelector('lit-main-menu') as LitMainMenu;
1272              let children = main.menus as Array<MenuGroup>;
1273              let child = children[0].children as Array<MenuItem>;
1274              let fileHandler = child[0].fileHandler;
1275              if (fileHandler && !SpRecordTrace.cancelRecord) {
1276                this.recordButtonText!.textContent = this.record;
1277                this.cancelButtonShow(false);
1278                this.freshMenuDisable(false);
1279                this.freshConfigMenuDisable(false);
1280                fileHandler({ detail: file });
1281              } else {
1282                SpRecordTrace.cancelRecord = false;
1283              }
1284            });
1285          } else {
1286            this.litSearch!.setPercent('tracing htrace failed, please check your config ', -2);
1287            this.recordButtonText!.textContent = this.record;
1288            this.freshMenuDisable(false);
1289            this.freshConfigMenuDisable(false);
1290            this.progressEL!.loading = false;
1291          }
1292          this.buttonDisable(false);
1293        });
1294      });
1295    });
1296  }
1297
1298  private initRecordCmdStatus(): void {
1299    this.appContent!.innerHTML = '';
1300    this.appContent!.append(this.traceCommand!);
1301    let config = this.makeRequest();
1302    this.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd(
1303      PluginConvertUtils.BeanToCmdTxt(config, false),
1304      this.recordSetting!.output,
1305      this.recordSetting!.maxDur
1306    );
1307    this.freshMenuItemsStatus('Trace command');
1308  }
1309
1310  private webRecordCmd(traceCommandStr: string, selectedOption: HTMLOptionElement): void {
1311    HdcDeviceManager.connect(selectedOption.value).then((result) => {
1312      log(`result is ${result}`);
1313      if (result) {
1314        this.initRecordCmdStatus();
1315        try {
1316          HdcDeviceManager.stopHiprofiler(CmdConstant.CMS_CANCEL).then(() => {
1317            HdcDeviceManager.shellResultAsString(CmdConstant.CMD_MOUNT, true).then(() => {
1318              this.sp!.search = true;
1319              this.progressEL!.loading = true;
1320              this.litSearch!.clear();
1321              this.litSearch!.setPercent(`tracing  ${this.recordSetting!.maxDur * 1000}ms`, -1);
1322              this.buttonDisable(true);
1323              this.freshMenuDisable(true);
1324              this.freshConfigMenuDisable(true);
1325              if (SpApplication.isLongTrace) {
1326                HdcDeviceManager.shellResultAsString(
1327                  `${CmdConstant.CMD_CLEAR_LONG_FOLD + this.recordSetting!.longOutPath}*`,
1328                  false
1329                ).then(() => {
1330                  HdcDeviceManager.shellResultAsString(
1331                    CmdConstant.CMD_MKDIR_LONG_FOLD + this.recordSetting!.longOutPath,
1332                    false
1333                  ).then(() => {
1334                    HdcDeviceManager.shellResultAsString(
1335                      CmdConstant.CMD_SET_FOLD_AUTHORITY + this.recordSetting!.longOutPath,
1336                      false
1337                    ).then(() => {
1338                      this.recordLongTraceCmd(traceCommandStr);
1339                    });
1340                  });
1341                });
1342              } else {
1343                this.recordTraceCmd(traceCommandStr);
1344              }
1345            });
1346          });
1347        } catch (e) {
1348          this.freshMenuDisable(false);
1349          this.freshConfigMenuDisable(false);
1350          this.buttonDisable(false);
1351        }
1352      } else {
1353        this.sp!.search = true;
1354        this.litSearch!.clear();
1355        this.litSearch!.setPercent('please kill other hdc-server !', -2);
1356      }
1357    });
1358  }
1359
1360  recordButtonListener(): void {
1361    SpRecordTrace.cancelRecord = false;
1362    let request = this.makeRequest();
1363    let isRecordArkTs = (this.spArkTs!.isStartArkts && this.spArkTs!.process.trim() !== '') ? true : false;
1364    if (request.pluginConfigs.length === 0 && !isRecordArkTs) {
1365      this.useExtentTip!.style.display = 'block';
1366      this.useExtentTip!.innerHTML = "It looks like you didn't add any probes. Please add at least one";
1367      return;
1368    }
1369    this.useExtentTip!.style.display = 'none';
1370    this.useExtentTip!.innerHTML = '';
1371    if (SpRecordTrace.useExtend) {
1372      this.recordButton!.hidden = true;
1373      this.buttonDisable(true, true);
1374      this.freshMenuDisable(true);
1375      this.freshConfigMenuDisable(true);
1376      this.recordPluginFunc();
1377      return;
1378    }
1379
1380    let traceCommandStr = PluginConvertUtils.createHdcCmd(
1381      PluginConvertUtils.BeanToCmdTxt(request, false),
1382      this.recordSetting!.output,
1383      this.recordSetting!.maxDur
1384    );
1385    let pluginList: Array<string> = [];
1386    request.pluginConfigs.forEach((pluginConfig) => {
1387      pluginList.push(pluginConfig.pluginName);
1388    });
1389    SpStatisticsHttpUtil.addOrdinaryVisitAction({
1390      action: 'config_page',
1391      event: 'online_record',
1392      eventData: {
1393        plugin: pluginList,
1394      },
1395    });
1396    let selectedOption = this.deviceSelect!.options[this.deviceSelect!.selectedIndex] as HTMLOptionElement;
1397    if (selectedOption) {
1398      SpRecordTrace.serialNumber = selectedOption.value;
1399    } else {
1400      this.sp!.search = true;
1401      this.litSearch!.clear();
1402      this.progressEL!.loading = false;
1403      this.litSearch!.setPercent('please connect device', -2);
1404    }
1405    if (this.vs) {
1406      this.appContent!.innerHTML = '';
1407      this.appContent!.append(this.traceCommand!);
1408      this.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd(
1409        PluginConvertUtils.BeanToCmdTxt(this.makeRequest(), false),
1410        this.recordSetting!.output,
1411        this.recordSetting!.maxDur
1412      );
1413      this.freshMenuItemsStatus('Trace command');
1414      this.vsCodeRecordCmd(traceCommandStr);
1415    } else {
1416      this.webRecordCmd(traceCommandStr, selectedOption);
1417    }
1418  }
1419
1420  private recordTraceCmd(traceCommandStr: string): void {
1421    let executeCmdCallBack = (cmdStateResult: string): void => {
1422      if (cmdStateResult.includes('tracing ')) {
1423        this.litSearch!.setPercent('Start to record...', -1);
1424      }
1425    };
1426    this.litSearch!.setPercent('Waiting to record...', -1);
1427    HdcDeviceManager.shellResultAsString(CmdConstant.CMD_SHELL + traceCommandStr, false, executeCmdCallBack).then((traceResult) => {
1428      let re = this.isSuccess(traceResult);
1429      if (re === 0) {
1430        this.litSearch!.setPercent('Tracing htrace down', -1);
1431        HdcDeviceManager.shellResultAsString(CmdConstant.CMD_TRACE_FILE_SIZE + this.recordSetting!.output, false).then(
1432          (traceFileSize) => {
1433            this.litSearch!.setPercent(`TraceFileSize is ${traceFileSize}`, -1);
1434            if (traceFileSize.indexOf('No such') !== -1) {
1435              this.refreshDisableStyle(false, true, 'No such file or directory', -2);
1436            } else if (Number(traceFileSize) <= MaxFileSize) {
1437              HdcDeviceManager.fileRecv(this.recordSetting!.output, (perNumber: number) => {
1438                this.litSearch!.setPercent('Downloading Hitrace file ', perNumber);
1439              }).then((pullRes) => {
1440                this.litSearch!.setPercent('Downloading Hitrace file ', 101);
1441                pullRes.arrayBuffer().then((buffer) => {
1442                  let fileName = this.recordSetting!.output.substring(this.recordSetting!.output.lastIndexOf('/') + 1);
1443                  let file = new File([buffer], fileName);
1444                  let main = this!.parentNode!.parentNode!.querySelector('lit-main-menu') as LitMainMenu;
1445                  let children = main.menus as Array<MenuGroup>;
1446                  let child = children[0].children as Array<MenuItem>;
1447                  let fileHandler = child[0].fileHandler;
1448                  if (fileHandler && !SpRecordTrace.cancelRecord) {
1449                    this.refreshDisableStyle(false, false);
1450                    fileHandler({
1451                      detail: file,
1452                    });
1453                  } else {
1454                    SpRecordTrace.cancelRecord = false;
1455                  }
1456                });
1457              });
1458            } else {
1459              this.recordButtonText!.textContent = this.record;
1460              this.refreshDisableStyle(false, true, 'Htrace file is too big', -2);
1461            }
1462          }
1463        );
1464      } else if (re === 2) {
1465        this.refreshDisableStyle(false, true, 'Stop tracing htrace ', -1);
1466      } else if (re === -1) {
1467        this.refreshDisableStyle(false, true, 'The device is abnormal', -2);
1468        this.progressEL!.loading = false;
1469      } else {
1470        this.refreshDisableStyle(false, true, 'Tracing htrace failed, please check your config ', -2);
1471      }
1472    });
1473  }
1474
1475  private recordLongTraceCmd(traceCommandStr: string): void {
1476    HdcDeviceManager.shellResultAsString(CmdConstant.CMD_SHELL + traceCommandStr, false).then((traceResult) => {
1477      let re = this.isSuccess(traceResult);
1478      if (re === 0) {
1479        this.litSearch!.setPercent('tracing htrace down', -1);
1480        HdcDeviceManager.shellResultAsString(
1481          CmdConstant.CMD_TRACE_FILE_SIZE + this.recordSetting!.longOutPath,
1482          false
1483        ).then((traceFileSize) => {
1484          this.litSearch!.setPercent(`traceFileSize is ${traceFileSize}`, -1);
1485          if (traceFileSize.indexOf('No such') !== -1) {
1486            this.litSearch!.setPercent('No such file or directory', -2);
1487            this.buttonDisable(false);
1488            this.freshConfigMenuDisable(false);
1489            this.freshMenuDisable(false);
1490          } else {
1491            this.recordLongTrace();
1492          }
1493        });
1494      } else if (re === 2) {
1495        this.refreshDisableStyle(false, true, 'stop tracing htrace ', -1);
1496      } else if (re === -1) {
1497        this.refreshDisableStyle(false, true, 'The device is abnormal', -2);
1498        this.progressEL!.loading = false;
1499      } else {
1500        this.refreshDisableStyle(false, true, 'tracing htrace failed, please check your config ', -2);
1501      }
1502    });
1503  }
1504
1505  private refreshDisableStyle(
1506    disable: boolean,
1507    isFreshSearch: boolean,
1508    percentName?: string,
1509    percentValue?: number
1510  ): void {
1511    if (isFreshSearch) {
1512      this.litSearch!.setPercent(percentName, percentValue!);
1513    }
1514    this.recordButtonDisable(disable);
1515    this.freshConfigMenuDisable(disable);
1516    this.freshMenuDisable(disable);
1517    this.buttonDisable(disable);
1518  }
1519
1520  private getLongTraceTypePage(): Array<number> {
1521    let traceTypePage: Array<number> = [];
1522    for (let fileIndex = 0; fileIndex < this.longTraceList.length; fileIndex++) {
1523      let traceFileName = this.longTraceList[fileIndex];
1524      if (this.sp!.fileTypeList.some((fileType) => traceFileName.toLowerCase().includes(fileType))) {
1525        continue;
1526      }
1527      let firstLastIndexOf = traceFileName.lastIndexOf('.');
1528      let firstText = traceFileName.slice(0, firstLastIndexOf);
1529      let resultLastIndexOf = firstText.lastIndexOf('_');
1530      traceTypePage.push(Number(firstText.slice(resultLastIndexOf + 1, firstText.length)) - 1);
1531    }
1532    traceTypePage.sort((leftNum: number, rightNum: number) => leftNum - rightNum);
1533    return traceTypePage;
1534  }
1535
1536  private loadLongTraceFile(timStamp: number): Promise<unknown> {
1537    return new Promise(async (resolve): Promise<void> => {
1538      let traceTypePage = this.getLongTraceTypePage();
1539      for (let fileIndex = 0; fileIndex < this.longTraceList.length; fileIndex++) {
1540        if (this.longTraceList[fileIndex] !== '') {
1541          let types = this.sp!.fileTypeList.filter((type) =>
1542            this.longTraceList[fileIndex].toLowerCase().includes(type.toLowerCase())
1543          );
1544          let pageNumber = 0;
1545          let fileType = types[0];
1546          if (types.length === 0) {
1547            fileType = 'trace';
1548            let searchNumber =
1549              Number(
1550                this.longTraceList[fileIndex].substring(
1551                  this.longTraceList[fileIndex].lastIndexOf('_') + 1,
1552                  this.longTraceList[fileIndex].lastIndexOf('.')
1553                )
1554              ) - 1;
1555            pageNumber = traceTypePage.lastIndexOf(searchNumber);
1556          }
1557          let pullRes = await HdcDeviceManager.fileRecv(
1558            this.recordSetting!.longOutPath + this.longTraceList[fileIndex],
1559            (perNumber: number) => {
1560              this.litSearch!.setPercent(`downloading ${fileType} file `, perNumber);
1561            }
1562          );
1563          this.litSearch!.setPercent(`downloading ${fileType} file `, 101);
1564          await this.saveIndexDBByLongTrace(pullRes, fileType, pageNumber, timStamp);
1565        }
1566      }
1567      resolve(1);
1568    });
1569  }
1570
1571  private async saveIndexDBByLongTrace(
1572    pullRes: Blob,
1573    fileType: string,
1574    pageNumber: number,
1575    timStamp: number
1576  ): Promise<void> {
1577    let buffer = await pullRes.arrayBuffer();
1578    let chunks = Math.ceil(buffer.byteLength / indexDBMaxSize);
1579    let offset = 0;
1580    let sliceLen = 0;
1581    let message = { fileType: '', startIndex: 0, endIndex: 0, size: 0 };
1582    for (let chunkIndex = 0; chunkIndex < chunks; chunkIndex++) {
1583      let start = chunkIndex * indexDBMaxSize;
1584      let end = Math.min(start + indexDBMaxSize, buffer.byteLength);
1585      let chunk = buffer.slice(start, end);
1586      if (chunkIndex === 0) {
1587        message.fileType = fileType;
1588        message.startIndex = chunkIndex;
1589      }
1590      sliceLen = Math.min(buffer.byteLength - offset, indexDBMaxSize);
1591      if (chunkIndex === 0 && fileType === 'trace') {
1592        this.sp!.longTraceHeadMessageList.push({ pageNum: pageNumber, data: buffer.slice(offset, kbSize) });
1593      }
1594      this.sp!.longTraceDataList.push({
1595        index: chunkIndex,
1596        fileType: fileType,
1597        pageNum: pageNumber,
1598        startOffsetSize: offset,
1599        endOffsetSize: offset + sliceLen,
1600      });
1601      await LongTraceDBUtils.getInstance().indexedDBHelp.add(LongTraceDBUtils.getInstance().tableName, {
1602        buf: chunk,
1603        id: `${fileType}_${timStamp}_${pageNumber}_${chunkIndex}`,
1604        fileType: fileType,
1605        pageNum: pageNumber,
1606        startOffset: offset,
1607        endOffset: offset + sliceLen,
1608        index: chunkIndex,
1609        timStamp: timStamp,
1610      });
1611      offset += sliceLen;
1612      if (offset >= buffer.byteLength) {
1613        message.endIndex = chunkIndex;
1614        message.size = buffer.byteLength;
1615        this.longTraceFileMapHandler(pageNumber, message);
1616      }
1617    }
1618  }
1619
1620  private longTraceFileMapHandler(
1621    pageNumber: number,
1622    message: {
1623      fileType: string;
1624      startIndex: number;
1625      endIndex: number;
1626      size: number;
1627    }
1628  ): void {
1629    if (this.sp!.longTraceTypeMessageMap) {
1630      if (this.sp!.longTraceTypeMessageMap?.has(pageNumber)) {
1631        let oldTypeList = this.sp!.longTraceTypeMessageMap?.get(pageNumber);
1632        oldTypeList?.push(message);
1633        this.sp!.longTraceTypeMessageMap?.set(pageNumber, oldTypeList!);
1634      } else {
1635        this.sp!.longTraceTypeMessageMap?.set(pageNumber, [message]);
1636      }
1637    } else {
1638      this.sp!.longTraceTypeMessageMap = new Map();
1639      this.sp!.longTraceTypeMessageMap.set(pageNumber, [message]);
1640    }
1641  }
1642
1643  private recordLongTrace(): void {
1644    let querySelector = this.sp!.shadowRoot?.querySelector('.long_trace_page') as HTMLDivElement;
1645    if (querySelector) {
1646      querySelector.style.display = 'none';
1647    }
1648    HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_LONG_FILES + this.recordSetting!.longOutPath, false).then(
1649      (result) => {
1650        this.longTraceList = result.split('\n').filter((fileName) => Boolean(fileName));
1651        if (this.longTraceList.length > 0) {
1652          this.sp!.longTraceHeadMessageList = [];
1653          this.sp!.longTraceDataList = [];
1654          this.sp!.longTraceTypeMessageMap = undefined;
1655          let timStamp = new Date().getTime();
1656          this.loadLongTraceFile(timStamp).then(() => {
1657            let main = this!.parentNode!.parentNode!.querySelector('lit-main-menu') as LitMainMenu;
1658            let children = main.menus as Array<MenuGroup>;
1659            let child = children[1].children as Array<MenuItem>;
1660            let fileHandler = child[0].clickHandler;
1661            if (fileHandler && !SpRecordTrace.cancelRecord) {
1662              this.freshConfigMenuDisable(false);
1663              this.freshMenuDisable(false);
1664              this.buttonDisable(false);
1665              this.recordButtonDisable(false);
1666              fileHandler(
1667                {
1668                  detail: {
1669                    timeStamp: timStamp,
1670                  },
1671                },
1672                true
1673              );
1674            } else {
1675              SpRecordTrace.cancelRecord = false;
1676            }
1677          });
1678        }
1679      }
1680    );
1681  }
1682
1683  private initRecordUIState(): void {
1684    this.buttonDisable(true);
1685    this.freshMenuDisable(true);
1686    this.freshConfigMenuDisable(true);
1687  }
1688
1689  private isSuccess(traceResult: string): number {
1690    if (traceResult.indexOf('CreateSession FAIL') !== -1 || traceResult.indexOf('failed') !== -1) {
1691      return 1;
1692    } else if (traceResult.indexOf('Signal') !== -1) {
1693      return 2;
1694    } else if (traceResult.indexOf('signal(2)') !== -1) {
1695      return 0;
1696    } else if (traceResult.indexOf('The device is abnormal') !== -1) {
1697      return -1;
1698    } else {
1699      return 0;
1700    }
1701  }
1702
1703  private makeRequest = (isCreateArkTsConfig = true): CreateSessionRequest => {
1704    let request = createSessionRequest(this.recordSetting!);
1705    if (this.record_template === 'true') {
1706      let templateConfigs = this.spRecordTemplate?.getTemplateConfig();
1707      templateConfigs?.forEach((config) => {
1708        request.pluginConfigs.push(config);
1709      });
1710    } else {
1711      if (SpApplication.isLongTrace && request.sessionConfig) {
1712        request.sessionConfig.splitFile = true;
1713        request.sessionConfig!.splitFileMaxSizeMb = this.recordSetting!.longTraceSingleFileMaxSize;
1714        request.sessionConfig!.splitFileMaxNum = 20;
1715      }
1716      let reportingFrequency: number = 5;
1717      if (this.recordSetting!.maxDur <= 20) {
1718        reportingFrequency = 2;
1719      }
1720      createHTracePluginConfig(this.probesConfig!, request);
1721      createFpsPluginConfig(this.probesConfig!, request);
1722      createMonitorPlugin(this.probesConfig!, request);
1723      createMemoryPluginConfig(reportingFrequency, this.spVmTracker!, this.probesConfig!, request);
1724      createNativePluginConfig(reportingFrequency, this.spAllocations!, SpRecordTrace.selectVersion, request);
1725      createHiPerfConfig(reportingFrequency, this.spRecordPerf!, this.recordSetting!, request);
1726      createSystemConfig(this.spFileSystem!, this.recordSetting!, request);
1727      createSdkConfig(this.spSdkConfig!, request);
1728      createHiSystemEventPluginConfig(this.spHiSysEvent!, request);
1729      if (isCreateArkTsConfig) {
1730        createArkTsConfig(this.spArkTs!, this.recordSetting!, request);
1731      }
1732      createHiLogConfig(reportingFrequency, this.spHiLog!, request);
1733      createFFRTPluginConfig(this.spFFRTConfig!, SpRecordTrace.selectVersion, request);
1734      createXPowerConfig(this.spXPower!, request);
1735    }
1736    return request;
1737  };
1738
1739  initHtml(): string {
1740    return SpRecordTraceHtml;
1741  }
1742
1743  private freshConfigMenuDisable(disable: boolean): void {
1744    let querySelectors = this.shadowRoot?.querySelectorAll<LitMainMenuItem>('lit-main-menu-item');
1745    querySelectors!.forEach((item) => {
1746      if (item.title !== 'Hdc Shell') {
1747        if (disable) {
1748          item.style.pointerEvents = 'none';
1749        } else {
1750          item.style.pointerEvents = 'auto';
1751        }
1752        item.disabled = disable;
1753      }
1754    });
1755  }
1756
1757  public startRefreshDeviceList(): void {
1758    if (this.refreshDeviceTimer === undefined) {
1759      this.refreshDeviceTimer = window.setInterval((): void => {
1760        this.refreshDeviceList();
1761      }, 5000);
1762    }
1763  }
1764
1765  private recordButtonDisable(disable: boolean): void {
1766    this.recordButton!.style.pointerEvents = disable ? 'none' : 'auto';
1767  }
1768
1769  private buttonDisable(disable: boolean, isUseExtend = false): void {
1770    let pointerEventValue = 'auto';
1771    this.recordButtonText!.textContent = this.record;
1772    if (disable) {
1773      pointerEventValue = 'none';
1774      if (!isUseExtend) {
1775        this.recordButtonText!.textContent = this.stop;
1776      }
1777    }
1778    if (!isUseExtend) {
1779      this.cancelButtonShow(disable);
1780    }
1781    this.disconnectButton!.style.pointerEvents = pointerEventValue;
1782    this.addButton!.style.pointerEvents = pointerEventValue;
1783    this.deviceSelect!.style.pointerEvents = pointerEventValue;
1784    this.deviceVersion!.style.pointerEvents = pointerEventValue;
1785    this.useExtendCheck!.style.pointerEvents = pointerEventValue;// arkts trace
1786  }
1787
1788  private freshMenuItemsStatus(currentValue: string): void {
1789    let litMainMenuGroup = this.shadowRoot?.querySelector<LitMainMenuGroup>('lit-main-menu-group');
1790    let litMainMenuItemNodeListOf = litMainMenuGroup!.querySelectorAll<LitMainMenuItem>('lit-main-menu-item');
1791    litMainMenuItemNodeListOf.forEach((item) => {
1792      item.back = item.title === currentValue;
1793    });
1794  }
1795
1796  synchronizeDeviceList(): void {
1797    this.deviceSelect!.innerHTML = '';
1798    if (SpRecordTrace.serialNumber !== '') {
1799      for (let i = 0; i < this.hdcList.length; i++) {
1800        let dev = this.hdcList[i];
1801        // @ts-ignore
1802        let serialNumber = typeof (dev) === 'string' ? dev : dev.serialNumber;
1803        let option = document.createElement('option');
1804        option.className = 'select';
1805        //@ts-ignore
1806        option.selected = serialNumber === SpRecordTrace.serialNumber;
1807        //@ts-ignore
1808        option.value = serialNumber;
1809        //@ts-ignore
1810        option.textContent = serialNumber;
1811        this.deviceSelect!.appendChild(option);
1812        this.recordButton!.hidden = false;
1813        this.disconnectButton!.hidden = false;
1814        this.devicePrompt!.innerText = '';
1815      }
1816      if (SpRecordTrace.selectVersion && SpRecordTrace.selectVersion !== '') {
1817        this.setDeviceVersionSelect(SpRecordTrace.selectVersion);
1818      }
1819    }
1820  }
1821}
1822
1823const kbSize = 1024;
1824const timeOut = 200;
1825const unitSize = 48;
1826const indexDBMaxSize = unitSize * kbSize * kbSize;
1827export const MaxFileSize: number = kbSize * kbSize * kbSize;
1828