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 { SpCheckDesBox } from './SpCheckDesBox'; 18import { LitCheckBox, LitCheckBoxChangeEvent } from '../../../base-ui/checkbox/LitCheckBox'; 19import { LitRadioGroup } from '../../../base-ui/radiobox/LitRadioGroup'; 20import { info, log } from '../../../log/Log'; 21import { LitSlider } from '../../../base-ui/slider/LitSlider'; 22import LitSwitch from '../../../base-ui/switch/lit-switch'; 23import { SpProbesConfigHtml } from './SpProbesConfig.html'; 24 25@element('probes-config') 26export class SpProbesConfig extends BaseElement { 27 private hitrace: SpCheckDesBox | undefined; 28 private _traceConfig: HTMLElement | undefined; 29 private _memoryConfig: HTMLElement | undefined | null; 30 private _abilityConfig: HTMLElement | undefined | null; 31 private ftraceBufferSizeResult: HTMLDivElement | null | undefined; 32 private ftraceSlider: LitSlider | null | undefined; 33 34 private ftraceBuffSizeResultInput: HTMLInputElement | null | undefined; 35 36 set startSamp(allocationStart: boolean) { 37 if (allocationStart) { 38 this.setAttribute('startSamp', ''); 39 } else { 40 this.removeAttribute('startSamp'); 41 } 42 } 43 44 get startSamp(): boolean { 45 return this.hasAttribute('startSamp'); 46 } 47 48 get traceConfig(): string[] { 49 let selectedTrace = this._traceConfig?.querySelectorAll<SpCheckDesBox>('check-des-box[checked]') || []; 50 let values = []; 51 for (const litCheckBoxElement of selectedTrace) { 52 values.push(litCheckBoxElement.value); 53 } 54 if (this.hitrace && this.hitrace.checked) { 55 values.push(this.hitrace.value); 56 } 57 info('traceConfig is :', values); 58 return values; 59 } 60 61 get ftraceBufferSize(): number { 62 if (this.ftraceBufferSizeResult?.hasAttribute('percent')) { 63 return Number(this.ftraceBufferSizeResult?.getAttribute('percent')); 64 } 65 return 20480; 66 } 67 68 get memoryConfig(): string[] { 69 let values = []; 70 let selectedMemory = this._memoryConfig?.querySelectorAll<SpCheckDesBox>( 71 'check-des-box[checked]' 72 ) as NodeListOf<SpCheckDesBox>; 73 for (const litCheckBoxElement of selectedMemory) { 74 values.push(litCheckBoxElement.value); 75 } 76 log(`memoryConfig size is :${values.length}`); 77 return values; 78 } 79 80 get recordAbility(): boolean { 81 let selectedMemory = this._abilityConfig?.querySelectorAll<SpCheckDesBox>( 82 'check-des-box[checked]' 83 ) as NodeListOf<SpCheckDesBox>; 84 return selectedMemory.length > 0; 85 } 86 87 get traceEvents(): string[] { 88 let values = []; 89 if (this.hitrace && this.hitrace.checked) { 90 let parent = this.shadowRoot?.querySelector('.user-events') as Element; 91 const siblingNode = parent?.querySelectorAll<LitCheckBox>('lit-check-box[name=userEvents][checked]'); 92 for (const litCheckBoxElement of siblingNode) { 93 values.push(litCheckBoxElement.value); 94 } 95 } 96 log(`traceEvents size is :${values.length}`); 97 return values; 98 } 99 100 get hilogConfig(): string[] { 101 let logLevel = this.shadowRoot?.getElementById('logLevel') as LitCheckBox; 102 if (logLevel.checked) { 103 let logRadio = this.shadowRoot?.getElementById('log-radio') as LitRadioGroup; 104 return logRadio.value; 105 } else { 106 return []; 107 } 108 } 109 110 private initTraceConfigList(): void { 111 this._traceConfig = this.shadowRoot?.querySelector('.trace-config') as HTMLElement; 112 traceConfigList.forEach((configBean) => { 113 let checkDesBox = new SpCheckDesBox(); 114 checkDesBox.value = configBean.value; 115 checkDesBox.checked = configBean.isSelect; 116 checkDesBox.des = configBean.des; 117 checkDesBox.addEventListener('onchange', () => { 118 this.dispatchEvent(new CustomEvent('addProbe', {})); 119 }); 120 this._traceConfig?.appendChild(checkDesBox); 121 }); 122 } 123 124 private initMemoryConfigList(): void { 125 this._memoryConfig = this.shadowRoot?.querySelector('.memory-config'); 126 memoryConfigList.forEach((configBean) => { 127 let checkDesBox = new SpCheckDesBox(); 128 checkDesBox.value = configBean.value; 129 checkDesBox.checked = configBean.isSelect; 130 checkDesBox.des = configBean.des; 131 checkDesBox.addEventListener('onchange', () => { 132 this.dispatchEvent(new CustomEvent('addProbe', {})); 133 }); 134 this._memoryConfig?.appendChild(checkDesBox); 135 }); 136 } 137 138 private initAbilityConfigList(): void { 139 this._abilityConfig = this.shadowRoot?.querySelector('.ability-config'); 140 abilityConfigList.forEach((configBean) => { 141 let checkDesBox = new SpCheckDesBox(); 142 checkDesBox.value = configBean.value; 143 checkDesBox.checked = configBean.isSelect; 144 checkDesBox.des = configBean.des; 145 checkDesBox.addEventListener('onchange', () => { 146 this.dispatchEvent(new CustomEvent('addProbe', {})); 147 }); 148 this._abilityConfig?.appendChild(checkDesBox); 149 }); 150 } 151 152 private initHiTraceConfigList(): void { 153 this.hitrace = this.shadowRoot?.getElementById('hitrace') as SpCheckDesBox; 154 let parent = this.shadowRoot?.querySelector('.user-events') as Element; 155 hiTraceConfigList.forEach((hitraceConfig: unknown) => { 156 let litCheckBox = new LitCheckBox(); 157 litCheckBox.setAttribute('name', 'userEvents'); 158 //@ts-ignore 159 litCheckBox.value = hitraceConfig.value; 160 //@ts-ignore 161 litCheckBox.checked = hitraceConfig.isSelect; 162 litCheckBox.addEventListener('change', (ev: CustomEventInit<LitCheckBoxChangeEvent>) => { 163 let detail = ev.detail; 164 if (this.hitrace?.checked === false) { 165 this.hitrace.checked = detail!.checked; 166 } 167 if (!detail!.checked && this.hitrace?.checked === true) { 168 let hasChecked = false; 169 const nodes = parent?.querySelectorAll<LitCheckBox>('lit-check-box[name=userEvents]'); 170 nodes.forEach((vv) => { 171 if (vv.checked) { 172 hasChecked = true; 173 } 174 }); 175 if (!hasChecked) { 176 this.hitrace.checked = hasChecked; 177 } 178 } 179 this.dispatchEvent(new CustomEvent('addProbe', {})); 180 }); 181 parent.append(litCheckBox); 182 }); 183 } 184 185 initElements(): void { 186 this.ftraceBuffSizeResultInput = this.shadowRoot?.querySelector('.ftrace-buff-size-result') as HTMLInputElement; 187 this.ftraceBuffSizeResultInput!.addEventListener('keydown', (ev: unknown) => { 188 //@ts-ignore 189 if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { 190 //@ts-ignore 191 ev.preventDefault(); 192 } 193 }); 194 this.initTraceConfigList(); 195 this.initMemoryConfigList(); 196 this.initAbilityConfigList(); 197 this.initHiTraceConfigList(); 198 this.bufferSizeSliderInit(); 199 let litSwitch = this.shadowRoot?.querySelector('lit-switch') as LitSwitch; 200 this.ftraceSlider = this.shadowRoot?.querySelector<LitSlider>('#ftrace-buff-size-slider'); 201 litSwitch.addEventListener('change', (event: unknown) => { 202 //@ts-ignore 203 let detail = event.detail; 204 if (detail!.checked) { 205 this.unDisable(); 206 } else { 207 this.disable(); 208 } 209 }); 210 } 211 212 private bufferSizeSliderInit(): void { 213 let bufferSizeSlider = this.shadowRoot?.querySelector<LitSlider>('#ftrace-buff-size-slider') as LitSlider; 214 this.ftraceBufferSizeResult = this.shadowRoot?.querySelector('#ftrace-buff-size-div') as HTMLDivElement; 215 bufferSizeSlider.sliderStyle = { 216 minRange: 2048, 217 maxRange: 307200, 218 defaultValue: '204800', 219 resultUnit: 'KB', 220 stepSize: 2, 221 lineColor: 'var(--dark-color3,#46B1E3)', 222 buttonColor: '#999999', 223 }; 224 let bufferSizeSliderParent = bufferSizeSlider!.parentNode as Element; 225 let buffSizeResult = this.shadowRoot?.querySelector('.ftrace-buff-size-result') as HTMLInputElement; 226 buffSizeResult!.onkeydown = (ev): void => { 227 // @ts-ignore 228 if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { 229 ev.preventDefault(); 230 } 231 }; 232 buffSizeResult.value = bufferSizeSlider.sliderStyle.defaultValue; 233 bufferSizeSlider.addEventListener('input', () => { 234 buffSizeResult.parentElement!.classList.remove('border-red'); 235 if (this.ftraceBufferSizeResult!.hasAttribute('percent')) { 236 buffSizeResult.value = Number(this.ftraceBufferSizeResult!.getAttribute('percent')).toString(); 237 } else { 238 buffSizeResult.value = '20480'; 239 } 240 }); 241 bufferSizeSliderParent.setAttribute('percent', '20480'); 242 buffSizeResult.style.color = 'var(--dark-color1,#000000)'; 243 buffSizeResult.addEventListener('input', () => { 244 this.ftraceBuffSizeResultInputHandler(buffSizeResult, bufferSizeSliderParent, bufferSizeSlider); 245 }); 246 buffSizeResult.addEventListener('focusout', () => { 247 if (buffSizeResult.value.trim() === '') { 248 buffSizeResult.parentElement!.classList.remove('border-red'); 249 bufferSizeSliderParent.setAttribute('percent', '20480'); 250 buffSizeResult.value = '20480'; 251 buffSizeResult.style.color = 'var(--dark-color,#6a6f77)'; 252 bufferSizeSliderParent.setAttribute('percent', buffSizeResult.value); 253 bufferSizeSliderParent.setAttribute('percentValue', buffSizeResult.value); 254 bufferSizeSlider!.percent = buffSizeResult.value; 255 let htmlInputElement = bufferSizeSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 256 htmlInputElement.value = buffSizeResult.value; 257 } 258 }); 259 } 260 261 private ftraceBuffSizeResultInputHandler( 262 buffSizeResultEl: HTMLInputElement, 263 bufferSizeSliderParentEl: Element, 264 bufferSizeSliderEl: LitSlider 265 ): void { 266 if (this.ftraceBufferSizeResult!.hasAttribute('percent')) { 267 this.ftraceBufferSizeResult!.removeAttribute('percent'); 268 } 269 buffSizeResultEl.style.color = 'var(--dark-color1,#000000)'; 270 buffSizeResultEl.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 271 buffSizeResultEl.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 272 if (buffSizeResultEl.value.trim() === '') { 273 buffSizeResultEl.style.color = 'red'; 274 bufferSizeSliderParentEl.setAttribute('percent', '20480'); 275 return; 276 } 277 let ftraceBufferSize = Number(buffSizeResultEl.value); 278 if ( 279 ftraceBufferSize < bufferSizeSliderEl!.sliderStyle.minRange || 280 ftraceBufferSize > bufferSizeSliderEl!.sliderStyle.maxRange 281 ) { 282 buffSizeResultEl.parentElement!.classList.add('border-red'); 283 bufferSizeSliderParentEl.setAttribute('percent', '20480'); 284 } else { 285 buffSizeResultEl.parentElement!.classList.remove('border-red'); 286 bufferSizeSliderEl!.percent = buffSizeResultEl.value; 287 let htmlInputElement = bufferSizeSliderEl!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 288 htmlInputElement.value = buffSizeResultEl.value; 289 bufferSizeSliderParentEl.setAttribute('percent', buffSizeResultEl.value); 290 bufferSizeSliderParentEl.setAttribute('percentValue', buffSizeResultEl.value); 291 } 292 } 293 294 private unDisable(): void { 295 this.startSamp = true; 296 let checkDesBoxDis = this.shadowRoot?.querySelectorAll<SpCheckDesBox>('check-des-box'); 297 let litCheckBoxDis = this.shadowRoot?.querySelectorAll<LitCheckBox>('lit-check-box'); 298 let defaultSelected: unknown = []; 299 //@ts-ignore 300 defaultSelected = defaultSelected.concat(traceConfigList, memoryConfigList, abilityConfigList, hiTraceConfigList); 301 this.shadowRoot?.querySelector<SpCheckDesBox>("[value='Hitrace categories']")?.setAttribute('checked', 'true'); 302 this.ftraceSlider!.removeAttribute('disabled'); 303 checkDesBoxDis?.forEach((item: SpCheckDesBox) => { 304 item.removeAttribute('disabled'); 305 }); 306 litCheckBoxDis?.forEach((item: LitCheckBox) => { 307 item.removeAttribute('disabled'); 308 }); 309 //@ts-ignore 310 defaultSelected.filter((item: unknown) => { 311 //@ts-ignore 312 if (item.isSelect) { 313 //@ts-ignore 314 this.shadowRoot?.querySelector<SpCheckDesBox>(`[value='${item.value}']`)?.setAttribute('checked', 'true'); 315 } 316 }); 317 } 318 319 private disable(): void { 320 this.startSamp = false; 321 let checkDesBoxDis = this.shadowRoot?.querySelectorAll<SpCheckDesBox>('check-des-box'); 322 let litCheckBoxDis = this.shadowRoot?.querySelectorAll<LitCheckBox>('lit-check-box'); 323 324 this.ftraceSlider!.setAttribute('disabled', ''); 325 326 checkDesBoxDis?.forEach((item: SpCheckDesBox) => { 327 item.setAttribute('disabled', ''); 328 item.checked = false; 329 }); 330 331 litCheckBoxDis?.forEach((item: LitCheckBox) => { 332 item.setAttribute('disabled', ''); 333 item.checked = false; 334 }); 335 } 336 337 initHtml(): string { 338 return SpProbesConfigHtml; 339 } 340 341 //当 custom element首次被插入文档DOM时,被调用。 342 public connectedCallback(): void { 343 let parent = this.shadowRoot?.querySelector('.user-events') as Element; 344 const siblingNode = parent?.querySelectorAll<LitCheckBox>('lit-check-box[name=userEvents]'); 345 this.hitrace!.addEventListener('onchange', (ev: CustomEventInit<LitCheckBoxChangeEvent>) => { 346 let detail = ev.detail; 347 siblingNode.forEach((node) => { 348 node.checked = detail!.checked; 349 }); 350 this.dispatchEvent(new CustomEvent('addProbe', {})); 351 }); 352 } 353} 354 355const hiTraceConfigList = [ 356 { value: 'ability', isSelect: true }, 357 { value: 'accesscontrol', isSelect: false }, 358 { value: 'accessibility', isSelect: false }, 359 { value: 'account', isSelect: false }, 360 { value: 'ace', isSelect: true }, 361 { value: 'app', isSelect: true }, 362 { value: 'ark', isSelect: true }, 363 { value: 'binder', isSelect: true }, 364 { value: 'bluetooth', isSelect: false }, 365 { value: 'cloud', isSelect: false }, 366 { value: 'commonlibrary', isSelect: false }, 367 { value: 'daudio', isSelect: false }, 368 { value: 'dcamera', isSelect: false }, 369 { value: 'deviceauth', isSelect: false }, 370 { value: 'devicemanager', isSelect: false }, 371 { value: 'deviceprofile', isSelect: false }, 372 { value: 'dhfwk', isSelect: false }, 373 { value: 'dinput', isSelect: false }, 374 { value: 'disk', isSelect: true }, 375 { value: 'distributeddatamgr', isSelect: false }, 376 { value: 'dlpcre', isSelect: false }, 377 { value: 'dsched', isSelect: false }, 378 { value: 'dscreen', isSelect: false }, 379 { value: 'dslm', isSelect: false }, 380 { value: 'dsoftbus', isSelect: false }, 381 { value: 'ffrt', isSelect: false }, 382 { value: 'filemanagement', isSelect: false }, 383 { value: 'freq', isSelect: true }, 384 { value: 'graphic', isSelect: true }, 385 { value: 'gresource', isSelect: false }, 386 { value: 'hdcd', isSelect: false }, 387 { value: 'hdf', isSelect: false }, 388 { value: 'huks', isSelect: false }, 389 { value: 'i2c', isSelect: false }, 390 { value: 'idle', isSelect: true }, 391 { value: 'interconn', isSelect: false }, 392 { value: 'irq', isSelect: true }, 393 { value: 'mdfs', isSelect: false }, 394 { value: 'memory', isSelect: false }, 395 { value: 'memreclaim', isSelect: true }, 396 { value: 'misc', isSelect: false }, 397 { value: 'mmc', isSelect: true }, 398 { value: 'msdp', isSelect: false }, 399 { value: 'multimodalinput', isSelect: true }, 400 { value: 'musl', isSelect: false }, 401 { value: 'net', isSelect: false }, 402 { value: 'notification', isSelect: true }, 403 { value: 'nweb', isSelect: false }, 404 { value: 'ohos', isSelect: true }, 405 { value: 'pagecache', isSelect: true }, 406 { value: 'power', isSelect: false }, 407 { value: 'regulators', isSelect: false }, 408 { value: 'rpc', isSelect: true }, 409 { value: 'samgr', isSelect: false }, 410 { value: 'sched', isSelect: true }, 411 { value: 'sensors', isSelect: false }, 412 { value: 'sync', isSelect: true }, 413 { value: 'usb', isSelect: false }, 414 { value: 'ufs', isSelect: false }, 415 { value: 'useriam', isSelect: false }, 416 { value: 'virse', isSelect: false }, 417 { value: 'window', isSelect: true }, 418 { value: 'workq', isSelect: true }, 419 { value: 'zaudio', isSelect: true }, 420 { value: 'zcamera', isSelect: true }, 421 { value: 'zimage', isSelect: true }, 422 { value: 'zmedia', isSelect: true }, 423]; 424 425const traceConfigList = [ 426 { 427 value: 'Scheduling details', 428 isSelect: true, 429 des: 'enables high-detailed tracking of scheduling events', 430 }, 431 { 432 value: 'CPU Frequency and idle states', 433 isSelect: true, 434 des: 'Records cpu frequency and idle state change viaftrace', 435 }, 436 { 437 value: 'Advanced ftrace config', 438 isSelect: false, 439 des: 440 'Enable individual events and tune the kernel-tracing(ftrace) module.' + 441 'The events enabled here are in addition to those from' + 442 ' enabled by other probes.', 443 }, 444]; 445 446const memoryConfigList = [ 447 { 448 value: 'Kernel meminfo', 449 isSelect: false, 450 des: 'polling of /proc/meminfo', 451 }, 452 { 453 value: 'Virtual memory stats', 454 isSelect: false, 455 des: 456 'Periodically polls virtual memory stats from /proc/vmstat.' + 457 ' Allows to gather statistics about swap,' + 458 'eviction, compression and pagecache efficiency', 459 }, 460]; 461 462const abilityConfigList = [ 463 { 464 value: 'AbilityMonitor', 465 isSelect: false, 466 des: 'Tracks the AbilityMonitor', 467 }, 468]; 469