• 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 
16 import { ColorUtils } from '../../component/trace/base/ColorUtils';
17 import {
18   BaseStruct,
19   drawFlagLine,
20   drawLines,
21   drawLoading,
22   drawLoadingFrame,
23   drawSelection,
24   isFrameContainPoint,
25   PerfRender,
26   RequestMessage,
27 } from './ProcedureWorkerCommon';
28 import { TraceRow } from '../../component/trace/base/TraceRow';
29 
30 export class EnergyAnomalyRender extends PerfRender {
31   renderMainThread(
32     req: {
33       useCache: boolean;
34       context: CanvasRenderingContext2D;
35       type: string;
36       appName: string;
37       canvasWidth: number;
38     },
39     row: TraceRow<EnergyAnomalyStruct>
40   ) {
41     let list = row.dataList;
42     let filter = row.dataListCache;
43     anomaly(
44       list,
45       filter,
46       TraceRow.range!.startNS,
47       TraceRow.range!.endNS,
48       TraceRow.range!.totalNS,
49       row.frame,
50       req.appName,
51       req.useCache || !TraceRow.range!.refresh
52     );
53     if (list.length > 0) {
54       filter.length = 0;
55       list.forEach((item) => {
56         filter.push(item);
57       });
58     }
59     drawLoadingFrame(req.context, row.dataListCache, row);
60     req.context.beginPath();
61     let find = false;
62     let spApplication = document.getElementsByTagName('sp-application')[0];
63     let isDark = spApplication.hasAttribute('dark');
64     drawLegend(req, isDark);
65     for (let re of filter) {
66       EnergyAnomalyStruct.draw(req.context, re);
67       if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) {
68         EnergyAnomalyStruct.hoverEnergyAnomalyStruct = re;
69         find = true;
70       }
71     }
72     if (!find && row.isHover) EnergyAnomalyStruct.hoverEnergyAnomalyStruct = undefined;
73     req.context.fillStyle = ColorUtils.FUNC_COLOR[0];
74     req.context.strokeStyle = ColorUtils.FUNC_COLOR[0];
75     req.context.closePath();
76   }
77 
78   render(energyAnomalyRequest: RequestMessage, list: Array<any>, filter: Array<any>, dataList2: Array<any>) {}
79 }
80 
81 export function drawLegend(req: any, isDark?: boolean) {
82   req.context.font = '12px Arial';
83   let text = req.context.measureText('System Abnormality');
84   req.context.fillStyle = '#E64566';
85   req.context.strokeStyle = '#E64566';
86   let textColor = isDark ? '#FFFFFF' : '#333';
87   let canvasEndX = req.context.canvas.clientWidth - EnergyAnomalyStruct.OFFSET_WIDTH;
88   let rectPadding: number;
89   let textPadding: number;
90   let textMargin: number;
91   let currentTextWidth: number;
92   let lastTextMargin: number;
93   rectPadding = 280;
94   textPadding = 270;
95   textMargin = 250;
96   currentTextWidth = canvasEndX - textMargin + text.width;
97   lastTextMargin = currentTextWidth + 12;
98   req!.context.fillRect(canvasEndX - rectPadding, 12, 8, 8);
99   req.context.globalAlpha = 1;
100   req.context.fillStyle = textColor;
101   req.context.textBaseline = 'middle';
102   req.context.fillText('System Abnormality', canvasEndX - textPadding, 18);
103   req.context.fillStyle = '#FFC880';
104   req.context.strokeStyle = '#FFC880';
105   req.context.fillRect(currentTextWidth, 12, 8, 8);
106   req.context.globalAlpha = 1;
107   req.context.fillStyle = textColor;
108   req.context.textBaseline = 'middle';
109   req.context.fillText('Application Abnormality', lastTextMargin, 18);
110   req.context.fillStyle = '#333';
111 }
112 
113 export function anomaly(
114   arr: Array<any>,
115   res: Array<any>,
116   startNS: number,
117   endNS: number,
118   totalNS: number,
119   frame: any,
120   appName: string | undefined,
121   use: boolean
122 ) {
123   arr.length = 0;
124   if (use && res.length > 0) {
125     let pns = (endNS - startNS) / frame.width;
126     let y = frame.y;
127     for (let i = 0; i < res.length; i++) {
128       let it = res[i];
129       if ((it.startNS || 0) > startNS && (it.startNS || 0) < endNS) {
130         if (!it.frame) {
131           it.frame = {};
132           it.frame.y = y;
133         }
134         it.frame.height = 20 + radius * 2;
135         if (it.startNS + 50000 > (startNS || 0) && (it.startNS || 0) < (endNS || 0)) {
136           EnergyAnomalyStruct.setAnomalyFrame(it, pns, startNS || 0, endNS || 0, frame);
137           if (it.appKey === 'APPNAME' && it.eventValue.split(',').indexOf(appName) >= 0) {
138             arr.push(it);
139           }
140           if (it.appKey != 'APPNAME') {
141             arr.push(it);
142           }
143         }
144       } else {
145         it.frame = null;
146       }
147     }
148     return;
149   }
150 }
151 
152 export class EnergyAnomalyStruct extends BaseStruct {
153   static hoverEnergyAnomalyStruct: EnergyAnomalyStruct | undefined;
154   static selectEnergyAnomalyStruct: EnergyAnomalyStruct | undefined;
155   static SYSTEM_EXCEPTION = new Set([
156     'ANOMALY_SCREEN_OFF_ENERGY',
157     'ANOMALY_ALARM_WAKEUP',
158     'ANOMALY_KERNEL_WAKELOCK',
159     'ANOMALY_CPU_HIGH_FREQUENCY',
160     'ANOMALY_WAKEUP',
161   ]);
162   static OFFSET_WIDTH: number = 266;
163   id: number | undefined;
164   type: number | undefined;
165   startNS: number | undefined;
166   height: number | undefined;
167   eventName: string | undefined;
168   appKey: string | undefined;
169   eventValue: string | undefined;
170 
171   static draw(ctx: CanvasRenderingContext2D, data: EnergyAnomalyStruct) {
172     if (data.frame) {
173       EnergyAnomalyStruct.drawRoundRectPath(ctx, data.frame.x - 7, 20 - 7, radius, data);
174     }
175   }
176 
177   static drawRoundRectPath(
178     ctx: CanvasRenderingContext2D,
179     x: number,
180     y: number,
181     radius: number,
182     data: EnergyAnomalyStruct
183   ) {
184     ctx.beginPath();
185     ctx.arc(x + 7, y + 22, radius, 0, Math.PI * 2);
186     ctx.closePath();
187     let color = '';
188     if (EnergyAnomalyStruct.SYSTEM_EXCEPTION.has(<string>data.eventName)) {
189       color = '#E64566';
190     } else {
191       color = '#FFC880';
192     }
193     // 填充背景颜色
194     ctx.fillStyle = color;
195     ctx.fill();
196     ctx.stroke();
197     // 填充文字颜色
198     ctx.font = '12px Arial';
199     ctx.fillStyle = ColorUtils.GREY_COLOR;
200     ctx.textAlign = 'center';
201     ctx.fillText('E', x + 7, y + 23);
202   }
203 
204   static setAnomalyFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) {
205     if ((node.startNS || 0) < startNS) {
206       node.frame.x = 0;
207     } else {
208       node.frame.x = Math.floor(((node.startNS || 0) - startNS) / pns);
209     }
210     if ((node.startNS || 0) > endNS) {
211       node.frame.width = frame.width - node.frame.x;
212     } else {
213       node.frame.width = Math.ceil(((node.startNS || 0) - startNS) / pns - node.frame.x);
214     }
215     if (node.frame.width < 1) {
216       node.frame.width = 1;
217     }
218   }
219 }
220 let radius = 12;
221