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 { BaseStruct, dataFilterHandler, drawLoadingFrame, drawString } from './ProcedureWorkerCommon'; 17import { TraceRow } from '../../component/trace/base/TraceRow'; 18import { ColorUtils } from '../../component/trace/base/ColorUtils'; 19import { SpSystemTrace } from '../../component/SpSystemTrace'; 20 21export class AppStartupRender { 22 renderMainThread( 23 appStartReq: { 24 useCache: boolean; 25 appStartupContext: CanvasRenderingContext2D; 26 type: string; 27 }, 28 appStartUpRow: TraceRow<AppStartupStruct> 29 ): void { 30 let list = appStartUpRow.dataList; 31 let appStartUpfilter = appStartUpRow.dataListCache; 32 dataFilterHandler(list, appStartUpfilter, { 33 startKey: 'startTs', 34 durKey: 'dur', 35 startNS: TraceRow.range?.startNS ?? 0, 36 endNS: TraceRow.range?.endNS ?? 0, 37 totalNS: TraceRow.range?.totalNS ?? 0, 38 frame: appStartUpRow.frame, 39 paddingTop: 5, 40 useCache: appStartReq.useCache || !(TraceRow.range?.refresh ?? false), 41 }); 42 drawLoadingFrame(appStartReq.appStartupContext, appStartUpRow.dataListCache, appStartUpRow); 43 appStartReq.appStartupContext.globalAlpha = 0.6; 44 let find = false; 45 let offset = 3; 46 for (let re of appStartUpfilter) { 47 AppStartupStruct.draw(appStartReq.appStartupContext, re); 48 if (appStartUpRow.isHover) { 49 if ( 50 re.frame && 51 appStartUpRow.hoverX >= re.frame.x - offset && 52 appStartUpRow.hoverX <= re.frame.x + re.frame.width + offset 53 ) { 54 AppStartupStruct.hoverStartupStruct = re; 55 find = true; 56 } 57 } 58 } 59 if (!find && appStartUpRow.isHover) { 60 AppStartupStruct.hoverStartupStruct = undefined; 61 } 62 } 63} 64 65const padding = 3; 66export function AppStartupStructOnClick( 67 clickRowType: string, 68 sp: SpSystemTrace, 69 scrollToFuncHandler: Function, 70 entry?: AppStartupStruct, 71): Promise<unknown> { 72 return new Promise((resolve, reject) => { 73 if (clickRowType === TraceRow.ROW_TYPE_APP_STARTUP && (AppStartupStruct.hoverStartupStruct || entry)) { 74 AppStartupStruct.selectStartupStruct = entry || AppStartupStruct.hoverStartupStruct; 75 sp.traceSheetEL?.displayStartupData( 76 AppStartupStruct.selectStartupStruct!, 77 scrollToFuncHandler, 78 sp.currentRow!.dataListCache 79 ); 80 sp.timerShaftEL?.modifyFlagList(undefined); 81 reject(new Error()); 82 } else { 83 resolve(null); 84 } 85 }); 86} 87export class AppStartupStruct extends BaseStruct { 88 static hoverStartupStruct: AppStartupStruct | undefined; 89 static selectStartupStruct: AppStartupStruct | undefined; 90 static StartUpStep: string[] = [ 91 'ProcessTouchEvent', 92 'StartUIAbilityBySCB', 93 'LoadAbility', 94 'Application Launching', 95 'UI Ability Launching', 96 'UI Ability OnForeground', 97 'First Frame - APP Phase', 98 'First Frame - Render Phase', 99 ]; 100 startTs: number | undefined; 101 startName: number = 0; 102 dur: number | undefined; 103 value: string | undefined; 104 pid: number | undefined; 105 process: string | undefined; 106 tid: number | undefined; 107 itid: number | undefined; 108 endItid: number | undefined; 109 stepName: string | undefined; 110 StartSlice: string | undefined; 111 EndSlice: string | undefined; 112 113 static draw(ctx: CanvasRenderingContext2D, data: AppStartupStruct): void { 114 if (data.frame) { 115 ctx.globalAlpha = 1.0; 116 ctx.fillStyle = ColorUtils.colorForTid(data.startName!); 117 ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, data.frame.height); 118 if (data.frame.width > 7) { 119 ctx.textBaseline = 'middle'; 120 ctx.lineWidth = 1; 121 if (data.stepName === undefined) { 122 data.stepName = `${AppStartupStruct.getStartupName(data.startName)} (${(data.dur! / 1000000).toFixed(2)}ms)`; 123 } 124 let textColor = 125 ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.stepName || '', 0, ColorUtils.FUNC_COLOR.length)]; 126 ctx.fillStyle = ColorUtils.funcTextColor(textColor); 127 drawString(ctx, data.stepName, 2, data.frame, data); 128 } 129 if (data === AppStartupStruct.selectStartupStruct) { 130 ctx.strokeStyle = '#232c5d'; 131 ctx.lineWidth = 2; 132 ctx.strokeRect(data.frame.x, data.frame.y, data.frame.width, data.frame.height); 133 } 134 } 135 } 136 137 static getStartupName(step: number | undefined): string { 138 if (step === undefined || step < 0 || step > 7) { 139 return 'Unknown Start Step'; 140 } else { 141 return AppStartupStruct.StartUpStep[step]; 142 } 143 } 144} 145