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.js'; 17import { checkDesBean, SpCheckDesBox } from './SpCheckDesBox.js'; 18import { LitCheckBox, LitCheckBoxChangeEvent } from '../../../base-ui/checkbox/LitCheckBox.js'; 19import { LitRadioGroup } from '../../../base-ui/radiobox/LitRadioGroup.js'; 20import { info, log } from '../../../log/Log.js'; 21import { LitSlider } from '../../../base-ui/slider/LitSlider'; 22 23@element('probes-config') 24export class SpProbesConfig extends BaseElement { 25 private traceConfigList: Array<checkDesBean> | undefined; 26 private memoryConfigList: Array<checkDesBean> | undefined; 27 private abilityConfigList: Array<checkDesBean> | undefined; 28 private hitraceConfigList: Array<any> | undefined; 29 private hitrace: SpCheckDesBox | undefined; 30 31 private _traceConfig: HTMLElement | undefined; 32 private _memoryConfig: HTMLElement | undefined | null; 33 private _abilityConfig: HTMLElement | undefined | null; 34 private ftraceBufferSizeResult: HTMLDivElement | null | undefined; 35 36 get traceConfig() { 37 let selectedTrace = this._traceConfig?.querySelectorAll<SpCheckDesBox>(`check-des-box[checked]`) || []; 38 let values = []; 39 for (const litCheckBoxElement of selectedTrace) { 40 values.push(litCheckBoxElement.value); 41 } 42 if (this.hitrace && this.hitrace.checked) { 43 values.push(this.hitrace.value); 44 } 45 info('traceConfig is :', values); 46 return values; 47 } 48 49 get ftraceBufferSize(): number { 50 if (this.ftraceBufferSizeResult?.hasAttribute('percent')) { 51 return Number(this.ftraceBufferSizeResult?.getAttribute('percent')); 52 } 53 return 20480; 54 } 55 56 get memoryConfig() { 57 let values = []; 58 let selectedMemory = this._memoryConfig?.querySelectorAll<SpCheckDesBox>( 59 `check-des-box[checked]` 60 ) as NodeListOf<SpCheckDesBox>; 61 for (const litCheckBoxElement of selectedMemory) { 62 values.push(litCheckBoxElement.value); 63 } 64 log('memoryConfig size is :' + values.length); 65 return values; 66 } 67 68 get recordAbility() { 69 let selectedMemory = this._abilityConfig?.querySelectorAll<SpCheckDesBox>( 70 `check-des-box[checked]` 71 ) as NodeListOf<SpCheckDesBox>; 72 return selectedMemory.length > 0; 73 } 74 75 get traceEvents() { 76 let values = []; 77 if (this.hitrace && this.hitrace.checked) { 78 let parent = this.shadowRoot?.querySelector('.user-events') as Element; 79 const siblingNode = parent?.querySelectorAll<LitCheckBox>(`lit-check-box[name=userEvents][checked]`); 80 for (const litCheckBoxElement of siblingNode) { 81 values.push(litCheckBoxElement.value); 82 } 83 } 84 log('traceEvents size is :' + values.length); 85 return values; 86 } 87 88 get hilogConfig() { 89 let logLevel = this.shadowRoot?.getElementById('logLevel') as LitCheckBox; 90 if (logLevel.checked) { 91 let logRadio = this.shadowRoot?.getElementById('log-radio') as LitRadioGroup; 92 return logRadio.value; 93 } else { 94 return []; 95 } 96 } 97 98 initElements(): void { 99 this.traceConfigList = [ 100 { 101 value: 'Scheduling details', 102 isSelect: true, 103 des: 'enables high-detailed tracking of scheduling events', 104 }, 105 { 106 value: 'CPU Frequency and idle states', 107 isSelect: true, 108 des: 'Records cpu frequency and idle state change viaftrace', 109 }, 110 { 111 value: 'Advanced ftrace config', 112 isSelect: false, 113 des: 114 'Enable individual events and tune the kernel-tracing(ftrace) module.' + 115 'The events enabled here are in addition to those from' + 116 ' enabled by other probes.', 117 }, 118 ]; 119 this._traceConfig = this.shadowRoot?.querySelector('.trace-config') as HTMLElement; 120 this.traceConfigList.forEach((configBean) => { 121 let checkDesBox = new SpCheckDesBox(); 122 checkDesBox.value = configBean.value; 123 checkDesBox.checked = configBean.isSelect; 124 checkDesBox.des = configBean.des; 125 checkDesBox.addEventListener('onchange', () => { 126 this.dispatchEvent(new CustomEvent('addProbe', {})); 127 }); 128 this._traceConfig?.appendChild(checkDesBox); 129 }); 130 this.memoryConfigList = [ 131 { 132 value: 'Kernel meminfo', 133 isSelect: false, 134 des: 'polling of /proc/meminfo', 135 }, 136 { 137 value: 'Virtual memory stats', 138 isSelect: false, 139 des: 140 'Periodically polls virtual memory stats from /proc/vmstat.' + 141 ' Allows to gather statistics about swap,' + 142 'eviction, compression and pagecache efficiency', 143 }, 144 ]; 145 this._memoryConfig = this.shadowRoot?.querySelector('.memory-config'); 146 this.memoryConfigList.forEach((configBean) => { 147 let checkDesBox = new SpCheckDesBox(); 148 checkDesBox.value = configBean.value; 149 checkDesBox.checked = configBean.isSelect; 150 checkDesBox.des = configBean.des; 151 checkDesBox.addEventListener('onchange', () => { 152 this.dispatchEvent(new CustomEvent('addProbe', {})); 153 }); 154 this._memoryConfig?.appendChild(checkDesBox); 155 }); 156 this.abilityConfigList = [ 157 { 158 value: 'AbilityMonitor', 159 isSelect: false, 160 des: 'Tracks the AbilityMonitor', 161 }, 162 ]; 163 this._abilityConfig = this.shadowRoot?.querySelector('.ability-config'); 164 this.abilityConfigList.forEach((configBean) => { 165 let checkDesBox = new SpCheckDesBox(); 166 checkDesBox.value = configBean.value; 167 checkDesBox.checked = configBean.isSelect; 168 checkDesBox.des = configBean.des; 169 checkDesBox.addEventListener('onchange', () => { 170 this.dispatchEvent(new CustomEvent('addProbe', {})); 171 }); 172 this._abilityConfig?.appendChild(checkDesBox); 173 }); 174 175 this.hitraceConfigList = [ 176 { value: 'ability', isSelect: true }, 177 { value: 'accesscontrol', isSelect: false }, 178 { value: 'accessibility', isSelect: false }, 179 { value: 'account', isSelect: false }, 180 { value: 'ace', isSelect: true }, 181 { value: 'app', isSelect: true }, 182 { value: 'ark', isSelect: true }, 183 { value: 'binder', isSelect: true }, 184 { value: 'commonlibrary', isSelect: false }, 185 { value: 'daudio', isSelect: false }, 186 { value: 'dcamera', isSelect: false }, 187 { value: 'devicemanager', isSelect: false }, 188 { value: 'deviceprofile', isSelect: false }, 189 { value: 'dhfwk', isSelect: false }, 190 { value: 'dinput', isSelect: false }, 191 { value: 'disk', isSelect: true }, 192 { value: 'dlpcre', isSelect: false }, 193 { value: 'dsched', isSelect: false }, 194 { value: 'dscreen', isSelect: false }, 195 { value: 'dslm', isSelect: false }, 196 { value: 'dsoftbus', isSelect: false }, 197 { value: 'filemanagement', isSelect: false }, 198 { value: 'freq', isSelect: true }, 199 { value: 'graphic', isSelect: true }, 200 { value: 'gresource', isSelect: false }, 201 { value: 'huks', isSelect: false }, 202 { value: 'i2c', isSelect: false }, 203 { value: 'idle', isSelect: true }, 204 { value: 'irq', isSelect: true }, 205 { value: 'load', isSelect: false }, 206 { value: 'mdfs', isSelect: false }, 207 { value: 'memreclaim', isSelect: true }, 208 { value: 'misc', isSelect: false }, 209 { value: 'mmc', isSelect: true }, 210 { value: 'msdp', isSelect: false }, 211 { value: 'multimodalinput', isSelect: true }, 212 { value: 'net', isSelect: false }, 213 { value: 'notification', isSelect: false }, 214 { value: 'nweb', isSelect: false }, 215 { value: 'ohos', isSelect: true }, 216 { value: 'pagecache', isSelect: true }, 217 { value: 'power', isSelect: false }, 218 { value: 'regulators', isSelect: false }, 219 { value: 'rpc', isSelect: true }, 220 { value: 'samgr', isSelect: false }, 221 { value: 'sched', isSelect: true }, 222 { value: 'sensors', isSelect: false }, 223 { value: 'sync', isSelect: true }, 224 { value: 'ufs', isSelect: false }, 225 { value: 'useriam', isSelect: false }, 226 { value: 'window', isSelect: true }, 227 { value: 'workq', isSelect: true }, 228 { value: 'zaudio', isSelect: true }, 229 { value: 'zcamera', isSelect: true }, 230 { value: 'zimage', isSelect: true }, 231 { value: 'zmedia', isSelect: true }, 232 ]; 233 this.hitrace = this.shadowRoot?.getElementById('hitrace') as SpCheckDesBox; 234 let parent = this.shadowRoot?.querySelector('.user-events') as Element; 235 this.hitraceConfigList?.forEach((hitraceConfig: any) => { 236 let litCheckBox = new LitCheckBox(); 237 litCheckBox.setAttribute('name', 'userEvents'); 238 litCheckBox.value = hitraceConfig.value; 239 litCheckBox.checked = hitraceConfig.isSelect; 240 litCheckBox.addEventListener('change', (ev: CustomEventInit<LitCheckBoxChangeEvent>) => { 241 let detail = ev.detail; 242 if (this.hitrace?.checked == false) { 243 this.hitrace.checked = detail!.checked; 244 } 245 if (detail!.checked == false && this.hitrace?.checked == true) { 246 let hasChecked = false; 247 const nodes = parent?.querySelectorAll<LitCheckBox>(`lit-check-box[name=userEvents]`); 248 nodes.forEach((vv) => { 249 if (vv.checked) { 250 hasChecked = true; 251 } 252 }); 253 if (!hasChecked) { 254 this.hitrace.checked = hasChecked; 255 } 256 } 257 this.dispatchEvent(new CustomEvent('addProbe', {})); 258 }); 259 parent.append(litCheckBox); 260 }); 261 this.bufferSizeSliderInit(); 262 } 263 264 private bufferSizeSliderInit() { 265 let ftraceBufferSizeSlider = this.shadowRoot?.querySelector<LitSlider>('#ftrace-buff-size-slider') as LitSlider; 266 this.ftraceBufferSizeResult = this.shadowRoot?.querySelector('#ftrace-buff-size-div') as HTMLDivElement; 267 ftraceBufferSizeSlider.sliderStyle = { 268 minRange: 2048, 269 maxRange: 307200, 270 defaultValue: '20480', 271 resultUnit: 'KB', 272 stepSize: 2, 273 lineColor: 'var(--dark-color3,#46B1E3)', 274 buttonColor: '#999999', 275 }; 276 let ftraceBufferSizeSliderParent = ftraceBufferSizeSlider!.parentNode as Element; 277 let ftraceBuffSizeResultInput = this.shadowRoot?.querySelector('.ftrace-buff-size-result') as HTMLInputElement; 278 ftraceBuffSizeResultInput.value = ftraceBufferSizeSlider.sliderStyle.defaultValue; 279 ftraceBufferSizeSlider.addEventListener('input', (evt) => { 280 ftraceBuffSizeResultInput.parentElement!.classList.remove('border-red'); 281 if (this.ftraceBufferSizeResult!.hasAttribute('percent')) { 282 ftraceBuffSizeResultInput.value = Number(this.ftraceBufferSizeResult!.getAttribute('percent')).toString(); 283 } else { 284 ftraceBuffSizeResultInput.value = '20480'; 285 } 286 }); 287 ftraceBufferSizeSliderParent.setAttribute('percent', '20480'); 288 ftraceBuffSizeResultInput.style.color = 'var(--dark-color1,#000000)'; 289 ftraceBuffSizeResultInput.addEventListener('input', (ev) => { 290 if (this.ftraceBufferSizeResult!.hasAttribute('percent')) { 291 this.ftraceBufferSizeResult!.removeAttribute('percent'); 292 } 293 ftraceBuffSizeResultInput.style.color = 'var(--dark-color1,#000000)'; 294 ftraceBuffSizeResultInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 295 ftraceBuffSizeResultInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 296 if (ftraceBuffSizeResultInput.value.trim() == '') { 297 ftraceBuffSizeResultInput.style.color = 'red'; 298 ftraceBufferSizeSliderParent.setAttribute('percent', '20480'); 299 return; 300 } 301 let ftraceBufferSize = Number(ftraceBuffSizeResultInput.value); 302 if ( 303 ftraceBufferSize < ftraceBufferSizeSlider!.sliderStyle.minRange || 304 ftraceBufferSize > ftraceBufferSizeSlider!.sliderStyle.maxRange 305 ) { 306 ftraceBuffSizeResultInput.parentElement!.classList.add('border-red'); 307 ftraceBufferSizeSliderParent.setAttribute('percent', '20480'); 308 } else { 309 ftraceBuffSizeResultInput.parentElement!.classList.remove('border-red'); 310 ftraceBufferSizeSlider!.percent = ftraceBuffSizeResultInput.value; 311 let htmlInputElement = ftraceBufferSizeSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 312 htmlInputElement.value = ftraceBuffSizeResultInput.value; 313 ftraceBufferSizeSliderParent.setAttribute('percent', ftraceBuffSizeResultInput.value); 314 ftraceBufferSizeSliderParent.setAttribute('percentValue', ftraceBuffSizeResultInput.value); 315 } 316 }); 317 ftraceBuffSizeResultInput.addEventListener('focusout', (ev) => { 318 if (ftraceBuffSizeResultInput.value.trim() == '') { 319 ftraceBuffSizeResultInput.parentElement!.classList.remove('border-red'); 320 ftraceBufferSizeSliderParent.setAttribute('percent', '20480'); 321 ftraceBuffSizeResultInput.value = '20480'; 322 ftraceBuffSizeResultInput.style.color = 'var(--dark-color,#6a6f77)'; 323 ftraceBufferSizeSliderParent.setAttribute('percent', ftraceBuffSizeResultInput.value); 324 ftraceBufferSizeSliderParent.setAttribute('percentValue', ftraceBuffSizeResultInput.value); 325 ftraceBufferSizeSlider!.percent = ftraceBuffSizeResultInput.value; 326 let htmlInputElement = ftraceBufferSizeSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 327 htmlInputElement.value = ftraceBuffSizeResultInput.value; 328 } 329 }); 330 } 331 332 initHtml(): string { 333 return ` 334 <style> 335 .recordText { 336 font-family: Helvetica-Bold; 337 font-size: 1em; 338 color: var(--dark-color1,#000000); 339 line-height: 28px; 340 font-weight: 700; 341 margin-bottom: 20px; 342 } 343 344 :host{ 345 display: inline-block; 346 background: var(--dark-background3,#FFFFFF); 347 width: 100%; 348 height: 100%; 349 border-radius: 0px 16px 16px 0px; 350 } 351 352 .root { 353 margin-right: 30px; 354 padding-top: 30px; 355 padding-left: 54px; 356 margin-bottom: 30px; 357 font-size:16px; 358 } 359 360 .config-page { 361 height: 95%; 362 font-size: 0.875em; 363 } 364 365 .trace-config{ 366 display: flex; 367 flex-direction: column; 368 width: 50%; 369 gap: 10px; 370 margin-bottom: 20px; 371 } 372 373 .memory-config{ 374 display: grid; 375 grid-template-columns: repeat(2, 1fr); 376 border-style: solid none none none; 377 border-color: #D5D5D5; 378 padding-top: 15px; 379 margin-top: 15px; 380 gap: 10px; 381 } 382 383 .ability-config{ 384 display: grid; 385 grid-template-columns: repeat(2, 1fr); 386 border-style: solid none none none; 387 border-color: #D5D5D5; 388 padding-top: 15px; 389 margin-top: 15px; 390 gap: 10px; 391 } 392 393 .span-col-2{ 394 grid-column: span 2 / auto; 395 } 396 397 .log-config{ 398 display: grid; 399 grid-template-columns: repeat(2, 1fr); 400 border-style: solid none none none; 401 border-color: #D5D5D5; 402 padding-top: 15px; 403 gap: 10px; 404 } 405 406 #hitrace-cat{ 407 display: grid; 408 grid-template-columns: 1fr 1fr; 409 } 410 .user-events{ 411 display: grid; 412 grid-template-columns: repeat(4, 1fr); 413 grid-template-rows: repeat(2, 1fr); 414 gap: 10px; 415 margin-left: 15px;; 416 } 417 #ftrace-buff-size-div { 418 width: 100%; 419 height: min-content; 420 display: grid; 421 grid-template-columns: 1fr min-content; 422 } 423 .buffer-size-des { 424 opacity: 0.6; 425 font-family: Helvetica; 426 font-size: 1em; 427 color: var(--dark-color,#000000); 428 text-align: left; 429 line-height: 20px; 430 font-weight: 400; 431 } 432 .ftrace-buff-size-result-div{ 433 display: grid; 434 grid-template-rows: 1fr; 435 grid-template-columns: min-content min-content; 436 background-color: var(--dark-background5,#F2F2F2); 437 -webkit-appearance:none; 438 color:var(--dark-color,#6a6f77); 439 width: 150px; 440 margin: 0 20px 0 0; 441 height: 40px; 442 border-radius:20px; 443 outline:0; 444 border:1px solid var(--dark-border,#c8cccf); 445 } 446 .ftrace-buff-size-result{ 447 background-color: var(--dark-background5,#F2F2F2); 448 -webkit-appearance:none; 449 color:var(--dark-color,#6a6f77); 450 border: none; 451 text-align: center; 452 width: 90px; 453 font-size:14px; 454 outline:0; 455 margin: 5px 0 5px 5px; 456 } 457 .border-red { 458 border:1px solid red; 459 } 460 </style> 461 <div class="root"> 462 <div class="recordText" >Record mode</div> 463 <div class="config-page"> 464 <div> 465 <div class="trace-config"></div> 466 <div class="span-col-2" id="hitrace-cat"> 467 <check-des-box id="hitrace" checked="true" value ="Hitrace categories" des="Enables C++ codebase annotations (HTRACE_BEGIN() / os.Trace())"> 468 </check-des-box> 469 <div class="user-events"> 470 <slot></slot> 471 </div> 472 </div> 473 <div> 474 <div> 475 <p>Buffer Size</p> 476 <p class="buffer-size-des">The ftrace buffer size range is 2048 KB to 307200 KB</p> 477 </div> 478 <div id="ftrace-buff-size-div"> 479 <lit-slider id="ftrace-buff-size-slider" defaultColor="var(--dark-color3,#46B1E3)" open dir="right"> 480 </lit-slider> 481 <div class='ftrace-buff-size-result-div'> 482 <input class="ftrace-buff-size-result" type="text" value='20480' onkeyup="this.value=this.value.replace(/\\D/g,'')"> 483 <span style="text-align: center; margin: 8px"> KB </span> 484 </div> 485 </div> 486 </div> 487 </div> 488 <div class="memory-config"> 489 <div class="span-col-2"> 490 <span>Memory Config</span> 491 </div> 492 </div> 493 <div class="ability-config"> 494 <div class="span-col-2"> 495 <span>Ability Config</span> 496 </div> 497 </div> 498 </div> 499 </div> 500 `; 501 } 502 503 //当 custom element首次被插入文档DOM时,被调用。 504 public connectedCallback() { 505 let parent = this.shadowRoot?.querySelector('.user-events') as Element; 506 const siblingNode = parent?.querySelectorAll<LitCheckBox>(`lit-check-box[name=userEvents]`); 507 this.hitrace!.addEventListener('onchange', (ev: CustomEventInit<LitCheckBoxChangeEvent>) => { 508 let detail = ev.detail; 509 siblingNode.forEach((node) => { 510 node.checked = detail!.checked; 511 }); 512 this.dispatchEvent(new CustomEvent('addProbe', {})); 513 }); 514 } 515} 516