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