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