• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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: 'bluetooth', isSelect: false },
185      { value: 'cloud', isSelect: false },
186      { value: 'commonlibrary', isSelect: false },
187      { value: 'daudio', isSelect: false },
188      { value: 'dcamera', isSelect: false },
189      { value: 'deviceauth', isSelect: false },
190      { value: 'devicemanager', isSelect: false },
191      { value: 'deviceprofile', isSelect: false },
192      { value: 'dhfwk', isSelect: false },
193      { value: 'dinput', isSelect: false },
194      { value: 'disk', isSelect: true },
195      { value: 'distributeddatamgr', isSelect: false },
196      { value: 'dlpcre', isSelect: false },
197      { value: 'dsched', isSelect: false },
198      { value: 'dscreen', isSelect: false },
199      { value: 'dslm', isSelect: false },
200      { value: 'dsoftbus', isSelect: false },
201      { value: 'ffrt', isSelect: false },
202      { value: 'filemanagement', isSelect: false },
203      { value: 'freq', isSelect: true },
204      { value: 'graphic', isSelect: true },
205      { value: 'gresource', isSelect: false },
206      { value: 'hdcd', isSelect: false },
207      { value: 'hdf', isSelect: false },
208      { value: 'huks', isSelect: false },
209      { value: 'i2c', isSelect: false },
210      { value: 'idle', isSelect: true },
211      { value: 'interconn', isSelect: false },
212      { value: 'irq', isSelect: true },
213      { value: 'mdfs', isSelect: false },
214      { value: 'memory', isSelect: false },
215      { value: 'memreclaim', isSelect: true },
216      { value: 'misc', isSelect: false },
217      { value: 'mmc', isSelect: true },
218      { value: 'msdp', isSelect: false },
219      { value: 'multimodalinput', isSelect: true },
220      { value: 'musl', isSelect: false },
221      { value: 'net', isSelect: false },
222      { value: 'notification', isSelect: false },
223      { value: 'nweb', isSelect: false },
224      { value: 'ohos', isSelect: true },
225      { value: 'pagecache', isSelect: true },
226      { value: 'power', isSelect: false },
227      { value: 'regulators', isSelect: false },
228      { value: 'rpc', isSelect: true },
229      { value: 'samgr', isSelect: false },
230      { value: 'sched', isSelect: true },
231      { value: 'sensors', isSelect: false },
232      { value: 'sync', isSelect: true },
233      { value: 'usb', isSelect: false },
234      { value: 'ufs', isSelect: false },
235      { value: 'useriam', isSelect: false },
236      { value: 'window', isSelect: true },
237      { value: 'workq', isSelect: true },
238      { value: 'zaudio', isSelect: true },
239      { value: 'zcamera', isSelect: true },
240      { value: 'zimage', isSelect: true },
241      { value: 'zmedia', isSelect: true },
242    ];
243    this.hitrace = this.shadowRoot?.getElementById('hitrace') as SpCheckDesBox;
244    let parent = this.shadowRoot?.querySelector('.user-events') as Element;
245    this.hitraceConfigList?.forEach((hitraceConfig: any) => {
246      let litCheckBox = new LitCheckBox();
247      litCheckBox.setAttribute('name', 'userEvents');
248      litCheckBox.value = hitraceConfig.value;
249      litCheckBox.checked = hitraceConfig.isSelect;
250      litCheckBox.addEventListener('change', (ev: CustomEventInit<LitCheckBoxChangeEvent>) => {
251        let detail = ev.detail;
252        if (this.hitrace?.checked === false) {
253          this.hitrace.checked = detail!.checked;
254        }
255        if (detail!.checked === false && this.hitrace?.checked === true) {
256          let hasChecked = false;
257          const nodes = parent?.querySelectorAll<LitCheckBox>(`lit-check-box[name=userEvents]`);
258          nodes.forEach((vv) => {
259            if (vv.checked) {
260              hasChecked = true;
261            }
262          });
263          if (!hasChecked) {
264            this.hitrace.checked = hasChecked;
265          }
266        }
267        this.dispatchEvent(new CustomEvent('addProbe', {}));
268      });
269      parent.append(litCheckBox);
270    });
271    this.bufferSizeSliderInit();
272  }
273
274  private bufferSizeSliderInit() {
275    let ftraceBufferSizeSlider = this.shadowRoot?.querySelector<LitSlider>('#ftrace-buff-size-slider') as LitSlider;
276    this.ftraceBufferSizeResult = this.shadowRoot?.querySelector('#ftrace-buff-size-div') as HTMLDivElement;
277    ftraceBufferSizeSlider.sliderStyle = {
278      minRange: 2048,
279      maxRange: 307200,
280      defaultValue: '20480',
281      resultUnit: 'KB',
282      stepSize: 2,
283      lineColor: 'var(--dark-color3,#46B1E3)',
284      buttonColor: '#999999',
285    };
286    let ftraceBufferSizeSliderParent = ftraceBufferSizeSlider!.parentNode as Element;
287    let ftraceBuffSizeResultInput = this.shadowRoot?.querySelector('.ftrace-buff-size-result') as HTMLInputElement;
288    ftraceBuffSizeResultInput.value = ftraceBufferSizeSlider.sliderStyle.defaultValue;
289    ftraceBufferSizeSlider.addEventListener('input', (evt) => {
290      ftraceBuffSizeResultInput.parentElement!.classList.remove('border-red');
291      if (this.ftraceBufferSizeResult!.hasAttribute('percent')) {
292        ftraceBuffSizeResultInput.value = Number(this.ftraceBufferSizeResult!.getAttribute('percent')).toString();
293      } else {
294        ftraceBuffSizeResultInput.value = '20480';
295      }
296    });
297    ftraceBufferSizeSliderParent.setAttribute('percent', '20480');
298    ftraceBuffSizeResultInput.style.color = 'var(--dark-color1,#000000)';
299    ftraceBuffSizeResultInput.addEventListener('input', (ev) => {
300      if (this.ftraceBufferSizeResult!.hasAttribute('percent')) {
301        this.ftraceBufferSizeResult!.removeAttribute('percent');
302      }
303      ftraceBuffSizeResultInput.style.color = 'var(--dark-color1,#000000)';
304      ftraceBuffSizeResultInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
305      ftraceBuffSizeResultInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
306      if (ftraceBuffSizeResultInput.value.trim() === '') {
307        ftraceBuffSizeResultInput.style.color = 'red';
308        ftraceBufferSizeSliderParent.setAttribute('percent', '20480');
309        return;
310      }
311      let ftraceBufferSize = Number(ftraceBuffSizeResultInput.value);
312      if (
313        ftraceBufferSize < ftraceBufferSizeSlider!.sliderStyle.minRange ||
314        ftraceBufferSize > ftraceBufferSizeSlider!.sliderStyle.maxRange
315      ) {
316        ftraceBuffSizeResultInput.parentElement!.classList.add('border-red');
317        ftraceBufferSizeSliderParent.setAttribute('percent', '20480');
318      } else {
319        ftraceBuffSizeResultInput.parentElement!.classList.remove('border-red');
320        ftraceBufferSizeSlider!.percent = ftraceBuffSizeResultInput.value;
321        let htmlInputElement = ftraceBufferSizeSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement;
322        htmlInputElement.value = ftraceBuffSizeResultInput.value;
323        ftraceBufferSizeSliderParent.setAttribute('percent', ftraceBuffSizeResultInput.value);
324        ftraceBufferSizeSliderParent.setAttribute('percentValue', ftraceBuffSizeResultInput.value);
325      }
326    });
327    ftraceBuffSizeResultInput.addEventListener('focusout', (ev) => {
328      if (ftraceBuffSizeResultInput.value.trim() === '') {
329        ftraceBuffSizeResultInput.parentElement!.classList.remove('border-red');
330        ftraceBufferSizeSliderParent.setAttribute('percent', '20480');
331        ftraceBuffSizeResultInput.value = '20480';
332        ftraceBuffSizeResultInput.style.color = 'var(--dark-color,#6a6f77)';
333        ftraceBufferSizeSliderParent.setAttribute('percent', ftraceBuffSizeResultInput.value);
334        ftraceBufferSizeSliderParent.setAttribute('percentValue', ftraceBuffSizeResultInput.value);
335        ftraceBufferSizeSlider!.percent = ftraceBuffSizeResultInput.value;
336        let htmlInputElement = ftraceBufferSizeSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement;
337        htmlInputElement.value = ftraceBuffSizeResultInput.value;
338      }
339    });
340  }
341
342  initHtml(): string {
343    return `
344        <style>
345        .recordText {
346           font-family: Helvetica-Bold;
347           font-size: 1em;
348           color: var(--dark-color1,#000000);
349           line-height: 28px;
350           font-weight: 700;
351           margin-bottom: 20px;
352        }
353
354        :host{
355            display: inline-block;
356            background: var(--dark-background3,#FFFFFF);
357            width: 100%;
358            height: 100%;
359            border-radius: 0px 16px 16px 0px;
360        }
361
362        .root {
363            margin-right: 30px;
364            padding-top: 30px;
365            padding-left: 54px;
366            margin-bottom: 30px;
367            font-size:16px;
368        }
369
370        .config-page {
371            height: 95%;
372            font-size: 0.875em;
373        }
374
375        .trace-config{
376           display: flex;
377           flex-direction: column;
378           width: 50%;
379           gap: 10px;
380           margin-bottom: 20px;
381        }
382
383        .memory-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        .ability-config{
394           display: grid;
395           grid-template-columns: repeat(2, 1fr);
396           border-style: solid none none none;
397           border-color: #D5D5D5;
398           padding-top: 15px;
399           margin-top: 15px;
400           gap: 10px;
401        }
402
403        .span-col-2{
404           grid-column: span 2 / auto;
405        }
406
407        .log-config{
408           display: grid;
409           grid-template-columns: repeat(2, 1fr);
410           border-style: solid none none none;
411           border-color: #D5D5D5;
412           padding-top: 15px;
413           gap: 10px;
414        }
415
416        #hitrace-cat{
417           display: grid;
418           grid-template-columns: 1fr 1fr;
419        }
420        .user-events{
421           display: grid;
422           grid-template-columns: repeat(4, 1fr);
423           grid-template-rows: repeat(2, 1fr);
424           gap: 10px;
425           margin-left: 15px;;
426        }
427        #ftrace-buff-size-div {
428            width: 100%;
429            height: min-content;
430            display: grid;
431            grid-template-columns: 1fr min-content;
432        }
433        .buffer-size-des {
434            opacity: 0.6;
435            font-family: Helvetica;
436            font-size: 1em;
437            color: var(--dark-color,#000000);
438            text-align: left;
439            line-height: 20px;
440            font-weight: 400;
441        }
442        .ftrace-buff-size-result-div{
443            display: grid;
444            grid-template-rows: 1fr;
445            grid-template-columns:  min-content min-content;
446            background-color: var(--dark-background5,#F2F2F2);
447            -webkit-appearance:none;
448            color:var(--dark-color,#6a6f77);
449            width: 150px;
450            margin: 0 20px 0 0;
451            height: 40px;
452            border-radius:20px;
453            outline:0;
454            border:1px solid var(--dark-border,#c8cccf);
455        }
456        .ftrace-buff-size-result{
457            background-color: var(--dark-background5,#F2F2F2);
458            -webkit-appearance:none;
459            color:var(--dark-color,#6a6f77);
460            border: none;
461            text-align: center;
462            width: 90px;
463            font-size:14px;
464            outline:0;
465            margin: 5px 0 5px 5px;
466        }
467        .border-red {
468           border:1px solid red;
469        }
470        </style>
471        <div class="root">
472            <div class="recordText" >Record mode</div>
473            <div class="config-page">
474                <div>
475                    <div class="trace-config"></div>
476                    <div class="span-col-2" id="hitrace-cat">
477                      <check-des-box id="hitrace" checked="true" value ="Hitrace categories" des="Enables C++ codebase annotations (HTRACE_BEGIN() / os.Trace())">
478                      </check-des-box>
479                      <div class="user-events">
480                          <slot></slot>
481                      </div>
482                    </div>
483                    <div>
484                       <div>
485                          <p>Buffer Size</p>
486                          <p class="buffer-size-des">The ftrace buffer size range is 2048 KB to 307200 KB</p>
487                       </div>
488                       <div id="ftrace-buff-size-div">
489                          <lit-slider id="ftrace-buff-size-slider" defaultColor="var(--dark-color3,#46B1E3)" open dir="right">
490                          </lit-slider>
491                          <div class='ftrace-buff-size-result-div'>
492                              <input class="ftrace-buff-size-result" type="text" value='20480' onkeyup="this.value=this.value.replace(/\\D/g,'')">
493                              <span style="text-align: center; margin: 8px"> KB </span>
494                           </div>
495                       </div>
496                    </div>
497                </div>
498                <div class="memory-config">
499                    <div class="span-col-2">
500                      <span>Memory Config</span>
501                    </div>
502                </div>
503                <div class="ability-config">
504                    <div class="span-col-2">
505                      <span>Ability Config</span>
506                    </div>
507                </div>
508            </div>
509        </div>
510        `;
511  }
512
513  //当 custom element首次被插入文档DOM时,被调用。
514  public connectedCallback() {
515    let parent = this.shadowRoot?.querySelector('.user-events') as Element;
516    const siblingNode = parent?.querySelectorAll<LitCheckBox>(`lit-check-box[name=userEvents]`);
517    this.hitrace!.addEventListener('onchange', (ev: CustomEventInit<LitCheckBoxChangeEvent>) => {
518      let detail = ev.detail;
519      siblingNode.forEach((node) => {
520        node.checked = detail!.checked;
521      });
522      this.dispatchEvent(new CustomEvent('addProbe', {}));
523    });
524  }
525}
526