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 { TraceRow } from '../trace/base/TraceRow';
18fb726d48Sopenharmony_ciimport { renders } from '../../database/ui-worker/ProcedureWorker';
19fb726d48Sopenharmony_ciimport { info } from '../../../log/Log';
20fb726d48Sopenharmony_ciimport { ClockRender, ClockStruct } from '../../database/ui-worker/ProcedureWorkerClock';
21fb726d48Sopenharmony_ciimport { ColorUtils } from '../trace/base/ColorUtils';
22fb726d48Sopenharmony_ciimport { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU';
23fb726d48Sopenharmony_ciimport { Utils } from '../trace/base/Utils';
24fb726d48Sopenharmony_ciimport { clockDataSender } from '../../database/data-trafic/ClockDataSender';
25fb726d48Sopenharmony_ciimport { queryClockData } from '../../database/sql/Clock.sql';
26fb726d48Sopenharmony_ciimport { DmaFenceRender, DmaFenceStruct } from '../../database/ui-worker/ProcedureWorkerDmaFence';
27fb726d48Sopenharmony_ciimport { dmaFenceSender } from '../../database/data-trafic/dmaFenceSender';
28fb726d48Sopenharmony_ciimport { queryDmaFenceName } from '../../database/sql/dmaFence.sql';
29fb726d48Sopenharmony_ciimport { BaseStruct } from '../../bean/BaseStruct';
30fb726d48Sopenharmony_ciimport { promises } from 'dns';
31fb726d48Sopenharmony_ci
32fb726d48Sopenharmony_ciexport class SpClockChart {
33fb726d48Sopenharmony_ci  private readonly trace: SpSystemTrace;
34fb726d48Sopenharmony_ci
35fb726d48Sopenharmony_ci  constructor(trace: SpSystemTrace) {
36fb726d48Sopenharmony_ci    this.trace = trace;
37fb726d48Sopenharmony_ci  }
38fb726d48Sopenharmony_ci
39fb726d48Sopenharmony_ci  async init(parentRow?: TraceRow<BaseStruct>, traceId?: string): Promise<void> {
40fb726d48Sopenharmony_ci    let clockList = await queryClockData(traceId);
41fb726d48Sopenharmony_ci    if (clockList.length === 0) {
42fb726d48Sopenharmony_ci      return;
43fb726d48Sopenharmony_ci    }
44fb726d48Sopenharmony_ci    let folder = await this.initFolder(traceId);
45fb726d48Sopenharmony_ci    if (parentRow) {
46fb726d48Sopenharmony_ci      parentRow.addChildTraceRow(folder);
47fb726d48Sopenharmony_ci    } else {
48fb726d48Sopenharmony_ci      this.trace.rowsEL?.appendChild(folder);
49fb726d48Sopenharmony_ci    }
50fb726d48Sopenharmony_ci    await this.initData(folder, clockList, traceId);
51fb726d48Sopenharmony_ci    await this.initDmaFence(folder);
52fb726d48Sopenharmony_ci  }
53fb726d48Sopenharmony_ci
54fb726d48Sopenharmony_ci  private clockSupplierFrame(
55fb726d48Sopenharmony_ci    traceRow: TraceRow<ClockStruct>,
56fb726d48Sopenharmony_ci    it: {
57fb726d48Sopenharmony_ci      name: string;
58fb726d48Sopenharmony_ci      num: number;
59fb726d48Sopenharmony_ci      srcname: string;
60fb726d48Sopenharmony_ci      maxValue?: number;
61fb726d48Sopenharmony_ci    },
62fb726d48Sopenharmony_ci    isState: boolean,
63fb726d48Sopenharmony_ci    isScreenState: boolean,
64fb726d48Sopenharmony_ci  ): void {
65fb726d48Sopenharmony_ci    traceRow.supplierFrame = (): Promise<ClockStruct[]> => {
66fb726d48Sopenharmony_ci      let promiseData = null;
67fb726d48Sopenharmony_ci      if (it.name.endsWith(' Frequency')) {
68fb726d48Sopenharmony_ci        promiseData = clockDataSender(it.srcname, 'clockFrequency', traceRow);
69fb726d48Sopenharmony_ci      } else if (isState) {
70fb726d48Sopenharmony_ci        promiseData = clockDataSender(it.srcname, 'clockState', traceRow);
71fb726d48Sopenharmony_ci      } else if (isScreenState) {
72fb726d48Sopenharmony_ci        promiseData = clockDataSender('', 'screenState', traceRow);
73fb726d48Sopenharmony_ci      }
74fb726d48Sopenharmony_ci      if (promiseData === null) {
75fb726d48Sopenharmony_ci        // @ts-ignore
76fb726d48Sopenharmony_ci        return new Promise<Array<unknown>>((resolve) => resolve([]));
77fb726d48Sopenharmony_ci      } else {
78fb726d48Sopenharmony_ci        // @ts-ignore
79fb726d48Sopenharmony_ci        return promiseData.then((resultClock: Array<unknown>) => {
80fb726d48Sopenharmony_ci          for (let j = 0; j < resultClock.length; j++) {
81fb726d48Sopenharmony_ci            // @ts-ignore
82fb726d48Sopenharmony_ci            resultClock[j].type = 'measure'; // @ts-ignore
83fb726d48Sopenharmony_ci            if ((resultClock[j].value || 0) > it.maxValue!) {
84fb726d48Sopenharmony_ci              // @ts-ignore
85fb726d48Sopenharmony_ci              it.maxValue = resultClock[j].value || 0;
86fb726d48Sopenharmony_ci            }
87fb726d48Sopenharmony_ci            if (j > 0) {
88fb726d48Sopenharmony_ci              // @ts-ignore
89fb726d48Sopenharmony_ci              resultClock[j].delta = (resultClock[j].value || 0) - (resultClock[j - 1].value || 0);
90fb726d48Sopenharmony_ci            } else {
91fb726d48Sopenharmony_ci              // @ts-ignore
92fb726d48Sopenharmony_ci              resultClock[j].delta = 0;
93fb726d48Sopenharmony_ci            }
94fb726d48Sopenharmony_ci          }
95fb726d48Sopenharmony_ci          return resultClock;
96fb726d48Sopenharmony_ci        });
97fb726d48Sopenharmony_ci      }
98fb726d48Sopenharmony_ci    };
99fb726d48Sopenharmony_ci  }
100fb726d48Sopenharmony_ci
101fb726d48Sopenharmony_ci  private clockThreadHandler(
102fb726d48Sopenharmony_ci    traceRow: TraceRow<ClockStruct>,
103fb726d48Sopenharmony_ci    it: {
104fb726d48Sopenharmony_ci      name: string;
105fb726d48Sopenharmony_ci      num: number;
106fb726d48Sopenharmony_ci      srcname: string;
107fb726d48Sopenharmony_ci      maxValue?: number;
108fb726d48Sopenharmony_ci    },
109fb726d48Sopenharmony_ci    isState: boolean,
110fb726d48Sopenharmony_ci    isScreenState: boolean,
111fb726d48Sopenharmony_ci    clockId: number
112fb726d48Sopenharmony_ci  ): void {
113fb726d48Sopenharmony_ci    traceRow.onThreadHandler = (useCache): void => {
114fb726d48Sopenharmony_ci      let context: CanvasRenderingContext2D;
115fb726d48Sopenharmony_ci      if (traceRow.currentContext) {
116fb726d48Sopenharmony_ci        context = traceRow.currentContext;
117fb726d48Sopenharmony_ci      } else {
118fb726d48Sopenharmony_ci        context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
119fb726d48Sopenharmony_ci      }
120fb726d48Sopenharmony_ci      traceRow.canvasSave(context);
121fb726d48Sopenharmony_ci      (renders.clock as ClockRender).renderMainThread(
122fb726d48Sopenharmony_ci        {
123fb726d48Sopenharmony_ci          context: context,
124fb726d48Sopenharmony_ci          useCache: useCache,
125fb726d48Sopenharmony_ci          type: it.name,
126fb726d48Sopenharmony_ci          maxValue: it.maxValue === 0 ? 1 : it.maxValue!,
127fb726d48Sopenharmony_ci          index: clockId,
128fb726d48Sopenharmony_ci          maxName:
129fb726d48Sopenharmony_ci            isState || isScreenState
130fb726d48Sopenharmony_ci              ? it.maxValue!.toString()
131fb726d48Sopenharmony_ci              : Utils.getFrequencyWithUnit(it.maxValue! / 1000).maxFreqName,
132fb726d48Sopenharmony_ci        },
133fb726d48Sopenharmony_ci        traceRow
134fb726d48Sopenharmony_ci      );
135fb726d48Sopenharmony_ci      traceRow.canvasRestore(context, this.trace);
136fb726d48Sopenharmony_ci    };
137fb726d48Sopenharmony_ci  }
138fb726d48Sopenharmony_ci
139fb726d48Sopenharmony_ci  async initData(folder: TraceRow<BaseStruct>, clockList: Array<{
140fb726d48Sopenharmony_ci    name: string;
141fb726d48Sopenharmony_ci    num: number;
142fb726d48Sopenharmony_ci    srcname: string;
143fb726d48Sopenharmony_ci    maxValue?: number;
144fb726d48Sopenharmony_ci  }>, traceId?: string): Promise<void> {
145fb726d48Sopenharmony_ci    let clockStartTime = new Date().getTime();
146fb726d48Sopenharmony_ci    info('clockList data size is: ', clockList!.length);
147fb726d48Sopenharmony_ci    if (!traceId) {
148fb726d48Sopenharmony_ci      this.trace.rowsEL?.appendChild(folder);
149fb726d48Sopenharmony_ci    }
150fb726d48Sopenharmony_ci    ClockStruct.maxValue = clockList.map((item) => item.num).reduce((a, b) => Math.max(a, b));
151fb726d48Sopenharmony_ci    for (let i = 0; i < clockList.length; i++) {
152fb726d48Sopenharmony_ci      const it = clockList[i];
153fb726d48Sopenharmony_ci      it.maxValue = 0;
154fb726d48Sopenharmony_ci      let traceRow = TraceRow.skeleton<ClockStruct>(traceId);
155fb726d48Sopenharmony_ci      let isState = it.name.endsWith(' State');
156fb726d48Sopenharmony_ci      let isScreenState = it.name.endsWith('ScreenState');
157fb726d48Sopenharmony_ci      traceRow.rowId = it.name;
158fb726d48Sopenharmony_ci      traceRow.rowType = TraceRow.ROW_TYPE_CLOCK;
159fb726d48Sopenharmony_ci      traceRow.rowParentId = folder.rowId;
160fb726d48Sopenharmony_ci      traceRow.style.height = '40px';
161fb726d48Sopenharmony_ci      traceRow.name = it.name;
162fb726d48Sopenharmony_ci      traceRow.rowHidden = !folder.expansion;
163fb726d48Sopenharmony_ci      traceRow.setAttribute('children', '');
164fb726d48Sopenharmony_ci      traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
165fb726d48Sopenharmony_ci      traceRow.selectChangeHandler = this.trace.selectChangeHandler;
166fb726d48Sopenharmony_ci      this.clockSupplierFrame(traceRow, it, isState, isScreenState);
167fb726d48Sopenharmony_ci      traceRow.getCacheData = (args: unknown): Promise<ClockStruct[]> | undefined => {
168fb726d48Sopenharmony_ci        let result: Promise<ClockStruct[]> | undefined;
169fb726d48Sopenharmony_ci        if (it.name.endsWith(' Frequency')) {
170fb726d48Sopenharmony_ci          result = clockDataSender(it.srcname, 'clockFrequency', traceRow, args);
171fb726d48Sopenharmony_ci        } else if (isState) {
172fb726d48Sopenharmony_ci          result = clockDataSender(it.srcname, 'clockState', traceRow, args);
173fb726d48Sopenharmony_ci        } else if (isScreenState) {
174fb726d48Sopenharmony_ci          result = clockDataSender('', 'screenState', traceRow, args);
175fb726d48Sopenharmony_ci        }
176fb726d48Sopenharmony_ci        return result;
177fb726d48Sopenharmony_ci      };
178fb726d48Sopenharmony_ci      traceRow.focusHandler = (ev): void => {
179fb726d48Sopenharmony_ci        this.trace?.displayTip(
180fb726d48Sopenharmony_ci          traceRow,
181fb726d48Sopenharmony_ci          ClockStruct.hoverClockStruct,
182fb726d48Sopenharmony_ci          `<span>${ColorUtils.formatNumberComma(ClockStruct.hoverClockStruct?.value!)}</span>`
183fb726d48Sopenharmony_ci        );
184fb726d48Sopenharmony_ci      };
185fb726d48Sopenharmony_ci      traceRow.findHoverStruct = (): void => {
186fb726d48Sopenharmony_ci        ClockStruct.hoverClockStruct = traceRow.getHoverStruct();
187fb726d48Sopenharmony_ci      };
188fb726d48Sopenharmony_ci      this.clockThreadHandler(traceRow, it, isState, isScreenState, i);
189fb726d48Sopenharmony_ci      folder.addChildTraceRow(traceRow);
190fb726d48Sopenharmony_ci    }
191fb726d48Sopenharmony_ci    let durTime = new Date().getTime() - clockStartTime;
192fb726d48Sopenharmony_ci    info('The time to load the ClockData is: ', durTime);
193fb726d48Sopenharmony_ci  }
194fb726d48Sopenharmony_ci
195fb726d48Sopenharmony_ci  // @ts-ignore
196fb726d48Sopenharmony_ci  async initDmaFence(folder: TraceRow<unknown>): Promise<void> {
197fb726d48Sopenharmony_ci    let dmaFenceNameList = await queryDmaFenceName();
198fb726d48Sopenharmony_ci    if (dmaFenceNameList.length) {
199fb726d48Sopenharmony_ci      let dmaFenceList = [];
200fb726d48Sopenharmony_ci      const timelineValues = dmaFenceNameList.map(obj => obj.timeline);
201fb726d48Sopenharmony_ci      for (let i = 0; i < timelineValues.length; i++) {
202fb726d48Sopenharmony_ci        let traceRow: TraceRow<DmaFenceStruct> = TraceRow.skeleton<DmaFenceStruct>();
203fb726d48Sopenharmony_ci        traceRow.rowId = timelineValues[i];
204fb726d48Sopenharmony_ci        traceRow.rowType = TraceRow.ROW_TYPE_DMA_FENCE;
205fb726d48Sopenharmony_ci        traceRow.rowParentId = folder.rowId;
206fb726d48Sopenharmony_ci        traceRow.style.height = 40 + 'px';
207fb726d48Sopenharmony_ci        traceRow.name = `${timelineValues[i]}`;
208fb726d48Sopenharmony_ci        traceRow.folder = false;
209fb726d48Sopenharmony_ci        traceRow.rowHidden = !folder.expansion;
210fb726d48Sopenharmony_ci        traceRow.setAttribute('children', '');
211fb726d48Sopenharmony_ci        traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
212fb726d48Sopenharmony_ci        traceRow.selectChangeHandler = this.trace.selectChangeHandler;
213fb726d48Sopenharmony_ci        // @ts-ignore
214fb726d48Sopenharmony_ci        traceRow.supplierFrame = (): Promise<DmaFenceStruct[]> => {
215fb726d48Sopenharmony_ci          return dmaFenceSender('dma_fence_init', `${timelineValues[i]}`, traceRow).then((res) => {
216fb726d48Sopenharmony_ci            res.forEach((item: unknown) => {
217fb726d48Sopenharmony_ci              // @ts-ignore
218fb726d48Sopenharmony_ci              let detail = Utils.DMAFENCECAT_MAP.get(item.id!);
219fb726d48Sopenharmony_ci              if (detail) {
220fb726d48Sopenharmony_ci                let catValue = (detail.cat.match(/^dma_(.*)$/))![1];
221fb726d48Sopenharmony_ci                // @ts-ignore
222fb726d48Sopenharmony_ci                item.sliceName = catValue.endsWith('ed') ? `${catValue.slice(0, -2)}(${detail.seqno})` : `${catValue}(${detail.seqno})`;
223fb726d48Sopenharmony_ci                // @ts-ignore
224fb726d48Sopenharmony_ci                item.driver = detail.driver;
225fb726d48Sopenharmony_ci                // @ts-ignore
226fb726d48Sopenharmony_ci                item.context = detail.context;
227fb726d48Sopenharmony_ci                // @ts-ignore
228fb726d48Sopenharmony_ci                item.depth = 0;
229fb726d48Sopenharmony_ci              }
230fb726d48Sopenharmony_ci
231fb726d48Sopenharmony_ci            });
232fb726d48Sopenharmony_ci            return dmaFenceList = res;
233fb726d48Sopenharmony_ci          });
234fb726d48Sopenharmony_ci
235fb726d48Sopenharmony_ci        };
236fb726d48Sopenharmony_ci        traceRow.onThreadHandler = (useCache): void => {
237fb726d48Sopenharmony_ci          let context: CanvasRenderingContext2D;
238fb726d48Sopenharmony_ci          if (traceRow.currentContext) {
239fb726d48Sopenharmony_ci            context = traceRow.currentContext;
240fb726d48Sopenharmony_ci          } else {
241fb726d48Sopenharmony_ci            context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
242fb726d48Sopenharmony_ci          }
243fb726d48Sopenharmony_ci          traceRow.canvasSave(context);
244fb726d48Sopenharmony_ci          (renders.dmaFence as DmaFenceRender).renderMainThread(
245fb726d48Sopenharmony_ci            {
246fb726d48Sopenharmony_ci              dmaFenceContext: context,
247fb726d48Sopenharmony_ci              useCache: useCache,
248fb726d48Sopenharmony_ci              type: 'dmaFence',
249fb726d48Sopenharmony_ci              maxValue: 20,
250fb726d48Sopenharmony_ci              index: 1,
251fb726d48Sopenharmony_ci              maxName: ''
252fb726d48Sopenharmony_ci            },
253fb726d48Sopenharmony_ci            traceRow
254fb726d48Sopenharmony_ci          );
255fb726d48Sopenharmony_ci          traceRow.canvasRestore(context, this.trace);
256fb726d48Sopenharmony_ci        };
257fb726d48Sopenharmony_ci        folder.addChildTraceRow(traceRow);
258fb726d48Sopenharmony_ci      }
259fb726d48Sopenharmony_ci
260fb726d48Sopenharmony_ci    }
261fb726d48Sopenharmony_ci
262fb726d48Sopenharmony_ci  }
263fb726d48Sopenharmony_ci
264fb726d48Sopenharmony_ci
265fb726d48Sopenharmony_ci  async initFolder(traceId?: string): Promise<TraceRow<BaseStruct>> {
266fb726d48Sopenharmony_ci    let clockFolder = TraceRow.skeleton(traceId);
267fb726d48Sopenharmony_ci    clockFolder.rowId = 'Clocks';
268fb726d48Sopenharmony_ci    clockFolder.index = 0;
269fb726d48Sopenharmony_ci    clockFolder.rowType = TraceRow.ROW_TYPE_CLOCK_GROUP;
270fb726d48Sopenharmony_ci    clockFolder.rowParentId = '';
271fb726d48Sopenharmony_ci    clockFolder.style.height = '40px';
272fb726d48Sopenharmony_ci    clockFolder.folder = true;
273fb726d48Sopenharmony_ci    clockFolder.name = 'Clocks';
274fb726d48Sopenharmony_ci    clockFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler;
275fb726d48Sopenharmony_ci    clockFolder.selectChangeHandler = this.trace.selectChangeHandler;
276fb726d48Sopenharmony_ci    clockFolder.supplier = (): Promise<BaseStruct[]> => new Promise<Array<BaseStruct>>((resolve) => resolve([]));
277fb726d48Sopenharmony_ci    clockFolder.onThreadHandler = (useCache): void => {
278fb726d48Sopenharmony_ci      clockFolder.canvasSave(this.trace.canvasPanelCtx!);
279fb726d48Sopenharmony_ci      if (clockFolder.expansion) {
280fb726d48Sopenharmony_ci        this.trace.canvasPanelCtx?.clearRect(0, 0, clockFolder.frame.width, clockFolder.frame.height);
281fb726d48Sopenharmony_ci      } else {
282fb726d48Sopenharmony_ci        (renders.empty as EmptyRender).renderMainThread(
283fb726d48Sopenharmony_ci          {
284fb726d48Sopenharmony_ci            context: this.trace.canvasPanelCtx,
285fb726d48Sopenharmony_ci            useCache: useCache,
286fb726d48Sopenharmony_ci            type: '',
287fb726d48Sopenharmony_ci          },
288fb726d48Sopenharmony_ci          clockFolder
289fb726d48Sopenharmony_ci        );
290fb726d48Sopenharmony_ci      }
291fb726d48Sopenharmony_ci      clockFolder.canvasRestore(this.trace.canvasPanelCtx!, this.trace);
292fb726d48Sopenharmony_ci    };
293fb726d48Sopenharmony_ci    return clockFolder;
294fb726d48Sopenharmony_ci  }
295fb726d48Sopenharmony_ci}
296