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