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