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