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 { CpuFreqStruct } from '../../database/ui-worker/ProcedureWorkerFreq';
20import {
21  queryAppStartupProcessIds,
22  queryProcessStartup,
23  querySingleAppStartupsName,
24} from '../../database/sql/ProcessThread.sql';
25import { FlagsConfig } from '../SpFlags';
26import { AllAppStartupStruct, AllAppStartupRender } from '../../database/ui-worker/ProcedureWorkerAllAppStartup';
27
28export class SpAllAppStartupsChart {
29  private readonly trace: SpSystemTrace | undefined;
30  static APP_STARTUP_PID_ARR: Array<number> = [];
31  static jsonRow: TraceRow<CpuFreqStruct> | undefined;
32  static trace: SpSystemTrace;
33  static AllAppStartupsNameArr: unknown[] = [];
34  static allAppStartupsAva: number[] = [];
35
36  constructor(trace: SpSystemTrace) {
37    SpAllAppStartupsChart.trace = trace;
38  }
39
40  async init(): Promise<void> {
41    SpAllAppStartupsChart.APP_STARTUP_PID_ARR = [];
42    let appStartUpPids = await queryAppStartupProcessIds();
43    appStartUpPids.forEach((it) => SpAllAppStartupsChart.APP_STARTUP_PID_ARR.push(it.pid));
44    SpAllAppStartupsChart.AllAppStartupsNameArr = [];
45    SpAllAppStartupsChart.allAppStartupsAva = [];
46    for (let i = 0; i < SpAllAppStartupsChart.APP_STARTUP_PID_ARR.length; i++) {
47      let tmpSingleApp: unknown[] = await queryProcessStartup(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]!);
48      if (tmpSingleApp.length === 8) {
49        let avilSingleName = await querySingleAppStartupsName(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]!);
50        SpAllAppStartupsChart.allAppStartupsAva.push(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]); //@ts-ignore
51        SpAllAppStartupsChart.AllAppStartupsNameArr.push(avilSingleName![0].name);
52      }
53    }
54    let loadAppStartup: boolean = FlagsConfig.getFlagsConfigEnableStatus('AppStartup');
55    if (loadAppStartup && SpAllAppStartupsChart.allAppStartupsAva.length) {
56      await this.initFolder();
57    }
58  }
59
60  private supplier(row: TraceRow<AllAppStartupStruct>): void {
61    row.supplier = async (): Promise<Array<AllAppStartupStruct>> => {
62      let sendRes: AllAppStartupStruct[] | PromiseLike<AllAppStartupStruct[]> = [];
63      for (let i = 0; i < SpAllAppStartupsChart.allAppStartupsAva.length; i++) {
64        let tmpResArr = await queryProcessStartup(SpAllAppStartupsChart.allAppStartupsAva[i]);
65        let maxStartTs: number | undefined = tmpResArr[0].startTs;
66        let minStartTs: number | undefined = tmpResArr[0].startTs;
67        let singleDur = tmpResArr[0].dur;
68        let endTs: number | undefined = tmpResArr[0].startTs;
69        if (tmpResArr.length > 1) {
70          for (let j = 0; j < tmpResArr.length; j++) {
71            if (Number(tmpResArr[j].startTs) > Number(maxStartTs)) {
72              maxStartTs = tmpResArr[j].startTs;
73            } else if (Number(tmpResArr[j].startTs) < Number(minStartTs)) {
74              minStartTs = tmpResArr[j].startTs;
75            }
76          }
77          tmpResArr.forEach((item) => {
78            if (item.startTs === maxStartTs) {
79              endTs = Number(item.startTs) + Number(item.dur);
80              singleDur = Number(endTs) - Number(minStartTs);
81            }
82          });
83        } else if (tmpResArr.length === 1) {
84          minStartTs = tmpResArr[0].startTs;
85          singleDur = tmpResArr[0].dur;
86        }
87        sendRes.push({
88          dur: singleDur,
89          startTs: minStartTs,
90          startName: undefined, // @ts-ignore
91          stepName: SpAllAppStartupsChart.AllAppStartupsNameArr[i],
92          translateY: undefined,
93          frame: undefined,
94          isHover: false,
95          value: undefined,
96          pid: undefined,
97          process: undefined,
98          tid: undefined,
99          itid: undefined,
100          endItid: undefined,
101        });
102      }
103      return sendRes;
104    };
105  }
106
107  async initFolder(): Promise<void> {
108    let row: TraceRow<AllAppStartupStruct> = TraceRow.skeleton<AllAppStartupStruct>();
109    row.setAttribute('hasStartup', 'true');
110    row.rowId = `all-app-start-${SpAllAppStartupsChart.APP_STARTUP_PID_ARR![0]}`;
111    row.index = 0;
112    row.rowType = TraceRow.ROW_TYPE_ALL_APPSTARTUPS;
113    row.rowParentId = '';
114    row.folder = false;
115    row.style.height = '40px';
116    row.name = 'All App Startups';
117    row.addTemplateTypes('AppStartup');
118    row.selectChangeHandler = SpAllAppStartupsChart.trace.selectChangeHandler;
119    row.favoriteChangeHandler = SpAllAppStartupsChart.trace.favoriteChangeHandler;
120    this.supplier(row);
121
122    row.onThreadHandler = (useCache): void => {
123      let context: CanvasRenderingContext2D;
124      if (row.currentContext) {
125        context = row.currentContext;
126      } else {
127        context = row.collect
128          ? SpAllAppStartupsChart.trace.canvasFavoritePanelCtx!
129          : SpAllAppStartupsChart.trace.canvasPanelCtx!;
130      }
131      row.canvasSave(context);
132      (renders['all-app-start-up'] as AllAppStartupRender).renderMainThread(
133        {
134          appStartupContext: context,
135          useCache: useCache,
136          type: `app-startup ${row.rowId}`,
137        },
138        row
139      );
140      row.canvasRestore(context, this.trace);
141    };
142    SpAllAppStartupsChart.trace.rowsEL?.appendChild(row);
143  }
144}
145