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 { log } from '../../../log/Log.js'; 18import { HdcDeviceManager } from '../../../hdc/HdcDeviceManager.js'; 19import { LitAllocationSelect } from '../../../base-ui/select/LitAllocationSelect.js'; 20import '../../../base-ui/select/LitAllocationSelect.js'; 21import { SpApplication } from '../../SpApplication.js'; 22import { LitSearch } from '../trace/search/Search.js'; 23import { SpRecordTrace } from '../SpRecordTrace.js'; 24import { Cmd } from '../../../command/Cmd.js'; 25import { CmdConstant } from '../../../command/CmdConstant.js'; 26import LitSwitch from '../../../base-ui/switch/lit-switch.js'; 27import { LitSlider } from '../../../base-ui/slider/LitSlider'; 28 29@element('sp-allocations') 30export class SpAllocations extends BaseElement { 31 private processId: LitAllocationSelect | null | undefined; 32 private unwindEL: HTMLInputElement | null | undefined; 33 private shareMemory: HTMLInputElement | null | undefined; 34 private shareMemoryUnit: HTMLSelectElement | null | undefined; 35 private filterMemory: HTMLInputElement | null | undefined; 36 private filterMemoryUnit: HTMLSelectElement | null | undefined; 37 private fpUnWind: LitSwitch | null | undefined; 38 39 private recordAccurately: LitSwitch | null | undefined; 40 private offlineSymbol: LitSwitch | null | undefined; 41 private recordStatisticsResult: HTMLDivElement | null | undefined; 42 43 get appProcess(): string { 44 return this.processId!.value || ''; 45 } 46 47 get unwind(): number { 48 log('unwind value is :' + this.unwindEL!.value); 49 return Number(this.unwindEL!.value); 50 } 51 52 get shared(): number { 53 let value = this.shareMemory?.value || ''; 54 log('shareMemory value is :' + value); 55 if (value != '') { 56 let unit = Number(this.shareMemory?.value) || 16384; 57 return unit; 58 } 59 return 16384; 60 } 61 62 get filter(): number { 63 let value = this.filterMemory?.value || ''; 64 log('filter value is :' + value); 65 if (value != '') { 66 return Number(value); 67 } 68 return 4096; 69 } 70 71 get fp_unwind(): boolean { 72 let value = this.fpUnWind?.checked; 73 if (value != undefined) { 74 return value; 75 } 76 return true; 77 } 78 79 get record_accurately(): boolean { 80 let value = this.recordAccurately?.checked; 81 if (value != undefined) { 82 return value; 83 } 84 return true; 85 } 86 87 get offline_symbolization(): boolean { 88 let value = this.offlineSymbol?.checked; 89 if (value != undefined) { 90 return value; 91 } 92 return true; 93 } 94 95 get record_statistics(): boolean { 96 if (this.recordStatisticsResult?.hasAttribute('percent')) { 97 let value = Number(this.recordStatisticsResult?.getAttribute('percent')); 98 return value > 0; 99 } 100 return true; 101 } 102 103 get statistics_interval(): number { 104 if (this.recordStatisticsResult?.hasAttribute('percentValue')) { 105 return Number(this.recordStatisticsResult?.getAttribute('percentValue')); 106 } 107 return 3600; 108 } 109 110 initElements(): void { 111 this.processId = this.shadowRoot?.getElementById('pid') as LitAllocationSelect; 112 let input = this.processId.shadowRoot?.querySelector('.multipleSelect') as HTMLDivElement; 113 let sp = document.querySelector('sp-application') as SpApplication; 114 let litSearch = sp?.shadowRoot?.querySelector('#lit-record-search') as LitSearch; 115 let allocationProcessData: Array<string> = []; 116 input.addEventListener('mousedown', (ev) => { 117 if (SpRecordTrace.serialNumber == '') { 118 this.processId!.processData = []; 119 } 120 }); 121 input.addEventListener('valuable', (ev) => { 122 this.dispatchEvent(new CustomEvent('addProbe', {})); 123 }); 124 input.addEventListener('inputClick', () => { 125 allocationProcessData = []; 126 if (SpRecordTrace.serialNumber != '') { 127 Cmd.getProcess().then((processList) => { 128 this.processId!.processData = processList; 129 this.processId!.initData(); 130 }); 131 } 132 }); 133 this.unwindEL = this.shadowRoot?.getElementById('unwind') as HTMLInputElement; 134 this.shareMemory = this.shadowRoot?.getElementById('shareMemory') as HTMLInputElement; 135 this.shareMemoryUnit = this.shadowRoot?.getElementById('shareMemoryUnit') as HTMLSelectElement; 136 this.filterMemory = this.shadowRoot?.getElementById('filterSized') as HTMLInputElement; 137 this.filterMemoryUnit = this.shadowRoot?.getElementById('filterSizedUnit') as HTMLSelectElement; 138 this.fpUnWind = this.shadowRoot?.getElementById('use_fp_unwind') as LitSwitch; 139 this.recordAccurately = this.shadowRoot?.getElementById('use_record_accurately') as LitSwitch; 140 this.offlineSymbol = this.shadowRoot?.getElementById('use_offline_symbolization') as LitSwitch; 141 let stepValue = [0, 1, 10, 30, 60, 300, 600, 1800, 3600]; 142 let statisticsSlider = this.shadowRoot?.querySelector<LitSlider>('#interval-slider') as LitSlider; 143 144 this.recordStatisticsResult = this.shadowRoot?.querySelector<HTMLDivElement>( 145 '.record-statistics-result' 146 ) as HTMLDivElement; 147 statisticsSlider.sliderStyle = { 148 minRange: 0, 149 maxRange: 3600, 150 defaultValue: '3600', 151 resultUnit: 'S', 152 stepSize: 450, 153 lineColor: 'var(--dark-color3,#46B1E3)', 154 buttonColor: '#999999', 155 }; 156 let parentElement = statisticsSlider!.parentNode as Element; 157 let intervalResultInput = this.shadowRoot?.querySelector('.interval-result') as HTMLInputElement; 158 intervalResultInput.value = statisticsSlider.sliderStyle.defaultValue; 159 statisticsSlider.addEventListener('input', (evt) => { 160 statisticsSlider!.sliderStyle = { 161 minRange: 0, 162 maxRange: 3600, 163 defaultValue: this.recordStatisticsResult!.getAttribute('percent') + '', 164 resultUnit: 'S', 165 stepSize: 450, 166 lineColor: 'var(--dark-color3,#46B1E3)', 167 buttonColor: '#999999', 168 }; 169 intervalResultInput.style.color = 'var(--dark-color1,#000000)'; 170 if (this.recordStatisticsResult!.hasAttribute('percent')) { 171 let step = Number(this.recordStatisticsResult!.getAttribute('percent')) / 450; 172 this.recordStatisticsResult!.setAttribute('percentValue', stepValue[step] + ''); 173 intervalResultInput.value = stepValue[step] + ''; 174 } 175 }); 176 parentElement.setAttribute('percent', '3600'); 177 intervalResultInput.style.color = 'var(--dark-color1,#000000)'; 178 intervalResultInput.addEventListener('input', (ev) => { 179 if (this.recordStatisticsResult!.hasAttribute('percent')) { 180 this.recordStatisticsResult!.removeAttribute('percent'); 181 } 182 intervalResultInput.style.color = 'var(--dark-color1,#000000)'; 183 intervalResultInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 184 intervalResultInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 185 if (intervalResultInput.value.trim() == '') { 186 intervalResultInput.style.color = 'red'; 187 parentElement.setAttribute('percent', '3600'); 188 return; 189 } 190 let memorySize = Number(intervalResultInput.value); 191 if (memorySize < statisticsSlider!.sliderStyle.minRange || memorySize > statisticsSlider!.sliderStyle.maxRange) { 192 intervalResultInput.style.color = 'red'; 193 parentElement.setAttribute('percent', '3600'); 194 } else { 195 statisticsSlider!.percent = intervalResultInput.value; 196 let htmlInputElement = statisticsSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 197 htmlInputElement.value = intervalResultInput.value; 198 statisticsSlider!.sliderStyle = { 199 minRange: 0, 200 maxRange: 3600, 201 defaultValue: intervalResultInput.value, 202 resultUnit: 'S', 203 stepSize: 1, 204 lineColor: 'var(--dark-color3,#46B1E3)', 205 buttonColor: '#999999', 206 }; 207 parentElement.setAttribute('percent', intervalResultInput.value); 208 parentElement.setAttribute('percentValue', intervalResultInput.value); 209 } 210 }); 211 212 intervalResultInput.addEventListener('focusout', (ev) => { 213 if (intervalResultInput.value.trim() == '') { 214 parentElement.setAttribute('percent', '3600'); 215 intervalResultInput.value = '3600'; 216 intervalResultInput.style.color = 'var(--dark-color,#6a6f77)'; 217 parentElement.setAttribute('percent', intervalResultInput.value); 218 parentElement.setAttribute('percentValue', intervalResultInput.value); 219 statisticsSlider!.percent = intervalResultInput.value; 220 let htmlInputElement = statisticsSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 221 htmlInputElement.value = intervalResultInput.value; 222 } 223 }); 224 statisticsSlider.shadowRoot?.querySelector<HTMLElement>('#slider')!.addEventListener('mouseup', (ev) => { 225 setTimeout(() => { 226 let percentValue = this.recordStatisticsResult!.getAttribute('percent'); 227 let index = Number(percentValue) / 450; 228 index = index < 1 ? 0 : index; 229 intervalResultInput.value = stepValue[index] + ''; 230 this.recordStatisticsResult!.setAttribute('percentValue', stepValue[index] + ''); 231 }); 232 }); 233 } 234 235 initHtml(): string { 236 return ` 237 <style> 238 .root { 239 padding-top: 45px; 240 margin-left: 40px; 241 display: grid; 242 grid-template-columns: repeat(2, 1fr); 243 grid-template-rows: min-content 1fr min-content; 244 width: 90%; 245 border-radius: 0px 16px 16px 0px; 246 } 247 :host{ 248 display: block; 249 width: 100%; 250 border-radius: 0px 16px 16px 0px; 251 height: 100%; 252 } 253 .title { 254 grid-column: span 2 / auto; 255 } 256 257 .font-style{ 258 font-family: Helvetica-Bold; 259 font-size: 1em; 260 color: var(--dark-color1,#000000); 261 line-height: 28px; 262 font-weight: 700; 263 } 264 .inner-font-style { 265 font-family: Helvetica,serif; 266 font-size: 1em; 267 color: var(--dark-color1,#000000); 268 text-align: left; 269 line-height: 20px; 270 font-weight: 400; 271 display:flex; 272 width:75%; 273 margin-top: 3px; 274 275 } 276 input { 277 width: 72%; 278 height: 25px; 279 border:0; 280 outline:none; 281 border-radius: 16px; 282 text-indent:2% 283 } 284 input::-webkit-input-placeholder{ 285 color:var(--bark-prompt,#999999); 286 } 287 .select { 288 height: 30px; 289 border:0; 290 border-radius: 3px; 291 outline:none; 292 border: 1px solid var(--dark-border,#B3B3B3); 293 width: 60px; 294 background-color:var(--dark-background5, #FFFFFF) 295 font-family: Helvetica; 296 font-size: 14px; 297 color:var(--dark-color,#212121) 298 text-align: center; 299 line-height: 16px; 300 font-weight: 400; 301 border-radius: 16px; 302 } 303 .application{ 304 display: flex; 305 flex-direction: column; 306 grid-gap: 15px; 307 margin-top: 40px; 308 } 309 .switchstyle{ 310 margin-top: 40px; 311 display: flex; 312 } 313 .inputstyle{ 314 background: var(--dark-background5,#FFFFFF); 315 border: 1px solid var(--dark-background5,#999999); 316 font-family: Helvetica; 317 font-size: 14px; 318 color: var(--dark-color1,#212121); 319 text-align: left; 320 line-height: 16px; 321 font-weight: 400; 322 } 323 .inputstyle::-webkit-input-placeholder { 324 background: var(--dark-background5,#FFFFFF); 325 } 326 #one_mb{ 327 background-color:var(--dark-background5, #FFFFFF) 328 } 329 #one_kb{ 330 background-color:var(--dark-background5, #FFFFFF) 331 } 332 #two_mb{ 333 background-color:var(--dark-background5, #FFFFFF) 334 } 335 #two_kb{ 336 background-color:var(--dark-background5, #FFFFFF) 337 } 338 .processSelect { 339 border-radius: 15px; 340 width: 84%; 341 } 342 .value-range { 343 opacity: 0.6; 344 font-family: Helvetica; 345 font-size: 1em; 346 color: var(--dark-color,#000000); 347 text-align: left; 348 line-height: 20px; 349 font-weight: 400; 350 } 351 .record-title{ 352 margin-bottom: 16px; 353 grid-column: span 3; 354 } 355 #interval-slider { 356 margin: 0 8px; 357 grid-column: span 2; 358 } 359 .resultSize{ 360 display: grid; 361 grid-template-rows: 1fr; 362 grid-template-columns: min-content min-content; 363 background-color: var(--dark-background5,#F2F2F2); 364 -webkit-appearance:none; 365 color:var(--dark-color,#6a6f77); 366 width: 150px; 367 margin: 0 30px 0 0; 368 height: 40px; 369 border-radius:20px; 370 outline:0; 371 border:1px solid var(--dark-border,#c8cccf); 372 } 373 .record-mode{ 374 font-family: Helvetica-Bold; 375 font-size: 1em; 376 color: var(--dark-color1,#000000); 377 line-height: 28px; 378 font-weight: 400; 379 margin-bottom: 16px; 380 grid-column: span 1; 381 } 382 .record-prompt{ 383 opacity: 0.6; 384 font-family: Helvetica; 385 font-size: 14px; 386 text-align: center; 387 line-height: 35px; 388 font-weight: 400; 389 } 390 .interval-result{ 391 background-color: var(--dark-background5,#F2F2F2); 392 -webkit-appearance:none; 393 color:var(--dark-color,#6a6f77); 394 border: none; 395 text-align: center; 396 width: 90px; 397 font-size:14px; 398 outline:0; 399 margin: 5px 0 5px 5px; 400 } 401 402 </style> 403 <div class="root"> 404 <div class = "title"> 405 <span class="font-style">Native Memory</span> 406 </div> 407 <div class="application"> 408 <span class="inner-font-style">ProcessId or ProcessName</span> 409 <span class="value-range">Record process</span> 410 <lit-allocation-select show-search class="processSelect" rounded default-value="" id="pid" placement="bottom" title="process" placeholder="please select process"> 411 </lit-allocation-select> 412 </div> 413 <div class="application"> 414 <span class="inner-font-style" >Max unwind level</span> 415 <span class="value-range">Max Unwind Level Rang is 0 - 512, default 10</span> 416 <input id= "unwind" class="inputstyle" type="text" placeholder="Enter the Max Unwind Level" oninput="if(this.value > 512) this.value = '512'" onkeyup="this.value=this.value.replace(/\\D/g,'')" value="10"> 417 </div> 418 <div class="application"> 419 <span class="inner-font-style">Shared Memory Size (One page equals 4 KB)</span> 420 <span class="value-range">Shared Memory Size Range is 0 - 131072 page, default 16384 page</span> 421 <div> 422 <input id = "shareMemory" class="inputstyle" type="text" placeholder="Enter the Shared Memory Size" oninput="if(this.value > 131072) this.value = '131072'" onkeyup="this.value=this.value.replace(/\\D/g,'')" value="16384"> 423 <span>Page</span> 424 </div> 425 </div> 426 <div class="application"> 427 <span class="inner-font-style" >Filter Memory Size </span> 428 <span class="value-range">Filter size Range is 0 - 65535 byte, default 4096 byte</span> 429 <div> 430 <input id = "filterSized" class="inputstyle" type="text" placeholder="Enter the Filter Memory Size" oninput="if(this.value > 65535) this.value = '65535'" onkeyup="this.value=this.value.replace(/\\D/g,'')" value="4096"> 431 <span>Byte</span> 432 </div> 433 </div> 434 <div class="switchstyle"> 435 <span class="inner-font-style" id="fp-unwind">Use Fp Unwind</span> 436 <lit-switch class="lts" id="use_fp_unwind" title="fp unwind" checked="true"></lit-switch> 437 </div> 438 <div class="switchstyle"> 439 <span class="inner-font-style" id="record_accurately ">Use Record Accurately (Available on recent OpenHarmony 4.0)</span> 440 <lit-switch class="lts" id="use_record_accurately" title="record_accurately" checked="true"></lit-switch> 441 </div> 442 <div class="switchstyle"> 443 <span class="inner-font-style" id="offline_symbolization">Use Offline Symbolization (Available on recent OpenHarmony 4.0)</span> 444 <lit-switch class="lts" id="use_offline_symbolization" title="offline_symbolization" checked="true"></lit-switch> 445 </div> 446 447 <div class="switchstyle record-statistics-result" style="grid-row: 6; grid-column: 1 / 3;height: min-content;display: grid;grid-template-rows: 1fr;grid-template-columns: 1fr min-content;"> 448 <div class="record-title"> 449 <span class="record-mode">Use Record Statistics (Available on recent OpenHarmony 4.0)</span> 450 <span class="record-prompt"> Time between following interval (0 = disabled) </span> 451 </div> 452 <lit-slider id="interval-slider" defaultColor="var(--dark-color3,#46B1E3)" open dir="right"> 453 </lit-slider> 454 <div class='resultSize'> 455 <input class="interval-result" type="text" value='0' onkeyup="this.value=this.value.replace(/\\D/g,'')"> 456 <span style="text-align: center; margin: 8px"> S </span> 457 </div> 458 </div> 459 </div> 460 `; 461 } 462 463 private convertToValue(input: string, unit: string): number { 464 let value: number; 465 switch (unit) { 466 case 'MB': 467 value = Number(input) * 1024 * 1024; 468 break; 469 case 'KB': 470 value = Number(input) * 1024; 471 break; 472 default: 473 value = 0; 474 } 475 let number = value / 4096; 476 if (number > 0 && number < 1) { 477 return 16384; 478 } 479 return parseInt(String(number)); 480 } 481} 482