1fb726d48Sopenharmony_ci/*
2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb726d48Sopenharmony_ci * You may obtain a copy of the License at
6fb726d48Sopenharmony_ci *
7fb726d48Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb726d48Sopenharmony_ci *
9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and
13fb726d48Sopenharmony_ci * limitations under the License.
14fb726d48Sopenharmony_ci */
15fb726d48Sopenharmony_ci
16fb726d48Sopenharmony_ciimport { SpSystemTrace } from '../SpSystemTrace';
17fb726d48Sopenharmony_ciimport { info } from '../../../log/Log';
18fb726d48Sopenharmony_ciimport { TraceRow } from '../trace/base/TraceRow';
19fb726d48Sopenharmony_ciimport { ColorUtils } from '../trace/base/ColorUtils';
20fb726d48Sopenharmony_ciimport { CpuFreqLimitRender, CpuFreqLimitsStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits';
21fb726d48Sopenharmony_ciimport { CpuFreqStruct, FreqRender } from '../../database/ui-worker/ProcedureWorkerFreq';
22fb726d48Sopenharmony_ciimport { CpuStateRender, CpuStateStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCpuState';
23fb726d48Sopenharmony_ciimport { folderSupplier, folderThreadHandler, rowThreadHandler } from './SpChartManager';
24fb726d48Sopenharmony_ciimport { Utils } from '../trace/base/Utils';
25fb726d48Sopenharmony_ciimport { cpuFreqDataSender } from '../../database/data-trafic/cpu/CpuFreqDataSender';
26fb726d48Sopenharmony_ciimport { cpuStateSender } from '../../database/data-trafic/cpu/CpuStateSender';
27fb726d48Sopenharmony_ciimport { cpuFreqLimitSender } from '../../database/data-trafic/cpu/CpuFreqLimitDataSender';
28fb726d48Sopenharmony_ciimport {
29fb726d48Sopenharmony_ci  getCpuLimitFreqId,
30fb726d48Sopenharmony_ci  getCpuLimitFreqMax,
31fb726d48Sopenharmony_ci  queryCpuFreq,
32fb726d48Sopenharmony_ci  queryCpuMaxFreq,
33fb726d48Sopenharmony_ci  queryCpuStateFilter,
34fb726d48Sopenharmony_ci} from '../../database/sql/Cpu.sql';
35fb726d48Sopenharmony_ciimport { BaseStruct } from '../../bean/BaseStruct';
36fb726d48Sopenharmony_ci
37fb726d48Sopenharmony_ciexport class SpFreqChart {
38fb726d48Sopenharmony_ci  private readonly trace: SpSystemTrace;
39fb726d48Sopenharmony_ci
40fb726d48Sopenharmony_ci  constructor(trace: SpSystemTrace) {
41fb726d48Sopenharmony_ci    this.trace = trace;
42fb726d48Sopenharmony_ci  }
43fb726d48Sopenharmony_ci
44fb726d48Sopenharmony_ci  async init(parentRow?: TraceRow<BaseStruct>, traceId?: string): Promise<void> {
45fb726d48Sopenharmony_ci    let freqList = await queryCpuFreq(traceId);
46fb726d48Sopenharmony_ci    let cpuStateFilterIds = await queryCpuStateFilter(traceId);
47fb726d48Sopenharmony_ci    //@ts-ignore
48fb726d48Sopenharmony_ci    this.trace.stateRowsId = cpuStateFilterIds;
49fb726d48Sopenharmony_ci    let cpuFreqLimits = await getCpuLimitFreqId(traceId);
50fb726d48Sopenharmony_ci    let cpuFreqLimitsMax = await getCpuLimitFreqMax(cpuFreqLimits.map((limit) => limit.maxFilterId).join(','), traceId);
51fb726d48Sopenharmony_ci    if (freqList.length > 0) {
52fb726d48Sopenharmony_ci      let folderRow = this.createFolderRow(traceId);
53fb726d48Sopenharmony_ci      folderRow.rowId = 'Cpu Frequency';
54fb726d48Sopenharmony_ci      folderRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_ALL;
55fb726d48Sopenharmony_ci      folderRow.name = 'Cpu Frequency';
56fb726d48Sopenharmony_ci      folderRow.selectChangeHandler = this.trace.selectChangeHandler;
57fb726d48Sopenharmony_ci      this.trace.rowsEL?.appendChild(folderRow);
58fb726d48Sopenharmony_ci      info('Cpu Freq data size is: ', freqList!.length);
59fb726d48Sopenharmony_ci      await this.addFreqRows(freqList, folderRow, traceId);
60fb726d48Sopenharmony_ci      if (parentRow) {
61fb726d48Sopenharmony_ci        parentRow.addChildTraceRow(folderRow);
62fb726d48Sopenharmony_ci      } else {
63fb726d48Sopenharmony_ci        this.trace.rowsEL?.appendChild(folderRow);
64fb726d48Sopenharmony_ci      }
65fb726d48Sopenharmony_ci    }
66fb726d48Sopenharmony_ci    if (cpuStateFilterIds.length > 0) {
67fb726d48Sopenharmony_ci      let folderRowState = this.createFolderRow();
68fb726d48Sopenharmony_ci      folderRowState.rowId = 'Cpu State';
69fb726d48Sopenharmony_ci      folderRowState.rowType = TraceRow.ROW_TYPE_CPU_STATE_ALL;
70fb726d48Sopenharmony_ci      folderRowState.name = 'Cpu State';
71fb726d48Sopenharmony_ci      folderRowState.selectChangeHandler = this.trace.selectChangeHandler;
72fb726d48Sopenharmony_ci      this.trace.rowsEL?.appendChild(folderRowState);
73fb726d48Sopenharmony_ci      this.addStateRows(cpuStateFilterIds, folderRowState, traceId);
74fb726d48Sopenharmony_ci      if (parentRow) {
75fb726d48Sopenharmony_ci        parentRow.addChildTraceRow(folderRowState);
76fb726d48Sopenharmony_ci      } else {
77fb726d48Sopenharmony_ci        this.trace.rowsEL?.appendChild(folderRowState);
78fb726d48Sopenharmony_ci      }
79fb726d48Sopenharmony_ci    }
80fb726d48Sopenharmony_ci    if (cpuFreqLimits.length > 0) {
81fb726d48Sopenharmony_ci      let folderRowLimit = this.createFolderRow();
82fb726d48Sopenharmony_ci      folderRowLimit.rowId = 'Cpu Freq Limit';
83fb726d48Sopenharmony_ci      folderRowLimit.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMITALL;
84fb726d48Sopenharmony_ci      folderRowLimit.name = 'Cpu Freq Limit';
85fb726d48Sopenharmony_ci      folderRowLimit.selectChangeHandler = this.trace.selectChangeHandler;
86fb726d48Sopenharmony_ci      this.trace.rowsEL?.appendChild(folderRowLimit);
87fb726d48Sopenharmony_ci      this.addFreqLimitRows(cpuFreqLimits, cpuFreqLimitsMax, folderRowLimit, traceId);
88fb726d48Sopenharmony_ci      if (parentRow) {
89fb726d48Sopenharmony_ci        parentRow.addChildTraceRow(folderRowLimit);
90fb726d48Sopenharmony_ci      } else {
91fb726d48Sopenharmony_ci        this.trace.rowsEL?.appendChild(folderRowLimit);
92fb726d48Sopenharmony_ci      }
93fb726d48Sopenharmony_ci    }
94fb726d48Sopenharmony_ci  }
95fb726d48Sopenharmony_ci
96fb726d48Sopenharmony_ci  createFolderRow(traceId?: string): TraceRow<BaseStruct> {
97fb726d48Sopenharmony_ci    let folder = TraceRow.skeleton<BaseStruct>(traceId);
98fb726d48Sopenharmony_ci    folder.rowParentId = '';
99fb726d48Sopenharmony_ci    folder.folder = true;
100fb726d48Sopenharmony_ci    folder.style.height = '40px';
101fb726d48Sopenharmony_ci    folder.rowHidden = folder.expansion;
102fb726d48Sopenharmony_ci    folder.setAttribute('children', '');
103fb726d48Sopenharmony_ci    folder.supplier = folderSupplier();
104fb726d48Sopenharmony_ci    folder.onThreadHandler = folderThreadHandler(folder, this.trace);
105fb726d48Sopenharmony_ci    return folder;
106fb726d48Sopenharmony_ci  }
107fb726d48Sopenharmony_ci
108fb726d48Sopenharmony_ci  async addFreqRows(
109fb726d48Sopenharmony_ci    freqList: Array<{ cpu: number; filterId: number }>,
110fb726d48Sopenharmony_ci    folderRow: TraceRow<BaseStruct>,
111fb726d48Sopenharmony_ci    traceId?: string
112fb726d48Sopenharmony_ci  ): Promise<void> {
113fb726d48Sopenharmony_ci    let freqMaxList = await queryCpuMaxFreq(traceId);
114fb726d48Sopenharmony_ci    CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq;
115fb726d48Sopenharmony_ci    let maxFreqObj = Utils.getFrequencyWithUnit(freqMaxList[0].maxFreq);
116fb726d48Sopenharmony_ci    CpuFreqStruct.maxFreq = maxFreqObj.maxFreq;
117fb726d48Sopenharmony_ci    CpuFreqStruct.maxFreqName = maxFreqObj.maxFreqName;
118fb726d48Sopenharmony_ci    for (let i = 0; i < freqList.length; i++) {
119fb726d48Sopenharmony_ci      const it = freqList[i];
120fb726d48Sopenharmony_ci      let traceRow = TraceRow.skeleton<CpuFreqStruct>(traceId);
121fb726d48Sopenharmony_ci      traceRow.rowId = `${it.filterId}`;
122fb726d48Sopenharmony_ci      traceRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ;
123fb726d48Sopenharmony_ci      traceRow.rowParentId = '';
124fb726d48Sopenharmony_ci      traceRow.style.height = '40px';
125fb726d48Sopenharmony_ci      traceRow.name = `Cpu ${it.cpu} Frequency`;
126fb726d48Sopenharmony_ci      traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
127fb726d48Sopenharmony_ci      traceRow.selectChangeHandler = this.trace.selectChangeHandler;
128fb726d48Sopenharmony_ci      traceRow.supplierFrame = (): Promise<CpuFreqStruct[]> => cpuFreqDataSender(it.cpu, traceRow);
129fb726d48Sopenharmony_ci      traceRow.focusHandler = (): void => {
130fb726d48Sopenharmony_ci        this.trace?.displayTip(
131fb726d48Sopenharmony_ci          traceRow,
132fb726d48Sopenharmony_ci          CpuFreqStruct.hoverCpuFreqStruct,
133fb726d48Sopenharmony_ci          `<span>${ColorUtils.formatNumberComma(CpuFreqStruct.hoverCpuFreqStruct?.value!)} kHz</span>`
134fb726d48Sopenharmony_ci        );
135fb726d48Sopenharmony_ci      };
136fb726d48Sopenharmony_ci      traceRow.findHoverStruct = (): void => {
137fb726d48Sopenharmony_ci        CpuFreqStruct.hoverCpuFreqStruct = traceRow.getHoverStruct(true, false, 'value');
138fb726d48Sopenharmony_ci      };
139fb726d48Sopenharmony_ci      traceRow.onThreadHandler = rowThreadHandler<FreqRender>(
140fb726d48Sopenharmony_ci        'freq',
141fb726d48Sopenharmony_ci        'context',
142fb726d48Sopenharmony_ci        {
143fb726d48Sopenharmony_ci          type: `freq${it.cpu}`,
144fb726d48Sopenharmony_ci        },
145fb726d48Sopenharmony_ci        traceRow,
146fb726d48Sopenharmony_ci        this.trace
147fb726d48Sopenharmony_ci      );
148fb726d48Sopenharmony_ci      folderRow!.addChildTraceRow(traceRow);
149fb726d48Sopenharmony_ci    }
150fb726d48Sopenharmony_ci  }
151fb726d48Sopenharmony_ci
152fb726d48Sopenharmony_ci  addStateRows(
153fb726d48Sopenharmony_ci    cpuStateFilterIds: Array<{ cpu: number; filterId: number }>,
154fb726d48Sopenharmony_ci    folderRowState: TraceRow<BaseStruct>,
155fb726d48Sopenharmony_ci    traceId?: string
156fb726d48Sopenharmony_ci  ): void {
157fb726d48Sopenharmony_ci    for (let it of cpuStateFilterIds) {
158fb726d48Sopenharmony_ci      let cpuStateRow = TraceRow.skeleton<CpuStateStruct>(traceId);
159fb726d48Sopenharmony_ci      cpuStateRow.rowId = `${it.filterId}`;
160fb726d48Sopenharmony_ci      cpuStateRow.rowType = TraceRow.ROW_TYPE_CPU_STATE;
161fb726d48Sopenharmony_ci      cpuStateRow.rowParentId = '';
162fb726d48Sopenharmony_ci      cpuStateRow.style.height = '40px';
163fb726d48Sopenharmony_ci      cpuStateRow.name = `Cpu ${it.cpu} State`;
164fb726d48Sopenharmony_ci      cpuStateRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
165fb726d48Sopenharmony_ci      cpuStateRow.selectChangeHandler = this.trace.selectChangeHandler;
166fb726d48Sopenharmony_ci      cpuStateRow.supplierFrame = async (): Promise<CpuStateStruct[]> => {
167fb726d48Sopenharmony_ci        let rs = await cpuStateSender(it.filterId, cpuStateRow);
168fb726d48Sopenharmony_ci        rs.forEach((t) => (t.cpu = it.cpu));
169fb726d48Sopenharmony_ci        return rs;
170fb726d48Sopenharmony_ci      };
171fb726d48Sopenharmony_ci      cpuStateRow.focusHandler = (): void => {
172fb726d48Sopenharmony_ci        this.trace.displayTip(
173fb726d48Sopenharmony_ci          cpuStateRow,
174fb726d48Sopenharmony_ci          CpuStateStruct.hoverStateStruct,
175fb726d48Sopenharmony_ci          `<span>State: ${CpuStateStruct.hoverStateStruct?.value}</span>`
176fb726d48Sopenharmony_ci        );
177fb726d48Sopenharmony_ci      };
178fb726d48Sopenharmony_ci      cpuStateRow.findHoverStruct = (): void => {
179fb726d48Sopenharmony_ci        CpuStateStruct.hoverStateStruct = cpuStateRow.getHoverStruct();
180fb726d48Sopenharmony_ci      };
181fb726d48Sopenharmony_ci      cpuStateRow.onThreadHandler = rowThreadHandler<CpuStateRender>(
182fb726d48Sopenharmony_ci        'cpu-state',
183fb726d48Sopenharmony_ci        'cpuStateContext',
184fb726d48Sopenharmony_ci        {
185fb726d48Sopenharmony_ci          type: `cpu-state-${it.cpu}`,
186fb726d48Sopenharmony_ci          cpu: it.cpu,
187fb726d48Sopenharmony_ci        },
188fb726d48Sopenharmony_ci        cpuStateRow,
189fb726d48Sopenharmony_ci        this.trace
190fb726d48Sopenharmony_ci      );
191fb726d48Sopenharmony_ci      folderRowState!.addChildTraceRow(cpuStateRow);
192fb726d48Sopenharmony_ci    }
193fb726d48Sopenharmony_ci  }
194fb726d48Sopenharmony_ci
195fb726d48Sopenharmony_ci  addFreqLimitRows(
196fb726d48Sopenharmony_ci    cpuFreqLimits: Array<CpuFreqRowLimit>,
197fb726d48Sopenharmony_ci    cpuFreqLimitsMax: Array<{ maxValue: number; filterId: number }>,
198fb726d48Sopenharmony_ci    folderRowLimit: TraceRow<BaseStruct>,
199fb726d48Sopenharmony_ci    traceId?: string
200fb726d48Sopenharmony_ci  ): void {
201fb726d48Sopenharmony_ci    for (let limit of cpuFreqLimits) {
202fb726d48Sopenharmony_ci      let findMax = Utils.getFrequencyWithUnit(
203fb726d48Sopenharmony_ci        cpuFreqLimitsMax.find((maxLimit) => maxLimit.filterId === limit.maxFilterId)?.maxValue || 0
204fb726d48Sopenharmony_ci      );
205fb726d48Sopenharmony_ci      let cpuFreqLimitRow = TraceRow.skeleton<CpuFreqLimitsStruct>(traceId);
206fb726d48Sopenharmony_ci      cpuFreqLimitRow.rowId = `${limit.cpu}`;
207fb726d48Sopenharmony_ci      cpuFreqLimitRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMIT;
208fb726d48Sopenharmony_ci      cpuFreqLimitRow.rowParentId = '';
209fb726d48Sopenharmony_ci      cpuFreqLimitRow.style.height = '40px';
210fb726d48Sopenharmony_ci      cpuFreqLimitRow.name = `Cpu ${limit.cpu} Freq Limit`;
211fb726d48Sopenharmony_ci      cpuFreqLimitRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
212fb726d48Sopenharmony_ci      cpuFreqLimitRow.selectChangeHandler = this.trace.selectChangeHandler;
213fb726d48Sopenharmony_ci      cpuFreqLimitRow.setAttribute('maxFilterId', `${limit.maxFilterId}`);
214fb726d48Sopenharmony_ci      cpuFreqLimitRow.setAttribute('minFilterId', `${limit.minFilterId}`);
215fb726d48Sopenharmony_ci      cpuFreqLimitRow.setAttribute('cpu', `${limit.cpu}`);
216fb726d48Sopenharmony_ci      cpuFreqLimitRow.supplierFrame = async (): Promise<CpuFreqLimitsStruct[]> => {
217fb726d48Sopenharmony_ci        const res =
218fb726d48Sopenharmony_ci          await cpuFreqLimitSender(limit.maxFilterId, limit.minFilterId, limit.cpu, cpuFreqLimitRow);
219fb726d48Sopenharmony_ci        res.forEach((item) => (item.cpu = limit.cpu));
220fb726d48Sopenharmony_ci        return res;
221fb726d48Sopenharmony_ci      };
222fb726d48Sopenharmony_ci      cpuFreqLimitRow.focusHandler = (ev): void => {
223fb726d48Sopenharmony_ci        this.trace.displayTip(
224fb726d48Sopenharmony_ci          cpuFreqLimitRow,
225fb726d48Sopenharmony_ci          CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct,
226fb726d48Sopenharmony_ci          `<span>Max Freq: ${ColorUtils.formatNumberComma(
227fb726d48Sopenharmony_ci            CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.max || 0
228fb726d48Sopenharmony_ci          )} kHz</span><span>Min Freq: ${ColorUtils.formatNumberComma(
229fb726d48Sopenharmony_ci            CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.min || 0
230fb726d48Sopenharmony_ci          )} kHz</span>`
231fb726d48Sopenharmony_ci        );
232fb726d48Sopenharmony_ci      };
233fb726d48Sopenharmony_ci      cpuFreqLimitRow.findHoverStruct = (): void => {
234fb726d48Sopenharmony_ci        CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = cpuFreqLimitRow.getHoverStruct();
235fb726d48Sopenharmony_ci      };
236fb726d48Sopenharmony_ci      cpuFreqLimitRow.onThreadHandler = rowThreadHandler<CpuFreqLimitRender>(
237fb726d48Sopenharmony_ci        'cpu-limit-freq',
238fb726d48Sopenharmony_ci        'context',
239fb726d48Sopenharmony_ci        {
240fb726d48Sopenharmony_ci          type: `cpu-limit-freq-${limit.cpu}`,
241fb726d48Sopenharmony_ci          cpu: limit.cpu,
242fb726d48Sopenharmony_ci          maxFreq: findMax?.maxFreq || 0,
243fb726d48Sopenharmony_ci          maxFreqName: findMax?.maxFreqName || '',
244fb726d48Sopenharmony_ci        },
245fb726d48Sopenharmony_ci        cpuFreqLimitRow,
246fb726d48Sopenharmony_ci        this.trace
247fb726d48Sopenharmony_ci      );
248fb726d48Sopenharmony_ci      folderRowLimit!.addChildTraceRow(cpuFreqLimitRow);
249fb726d48Sopenharmony_ci    }
250fb726d48Sopenharmony_ci  }
251fb726d48Sopenharmony_ci}
252fb726d48Sopenharmony_ci
253fb726d48Sopenharmony_ciexport class CpuFreqRowLimit {
254fb726d48Sopenharmony_ci  cpu: number = 0;
255fb726d48Sopenharmony_ci  maxFilterId: number = 0;
256fb726d48Sopenharmony_ci  minFilterId: number = 0;
257fb726d48Sopenharmony_ci}
258