• 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 { ColorUtils } from '../../component/trace/base/ColorUtils';
17import {
18  BaseStruct,
19  drawFlagLine,
20  drawLines,
21  drawLoading,
22  drawLoadingFrame,
23  drawSelection,
24  isFrameContainPoint,
25  PerfRender,
26  RequestMessage,
27} from './ProcedureWorkerCommon';
28import { TraceRow } from '../../component/trace/base/TraceRow';
29
30export 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
81export 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
113export 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
152export 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}
220let radius = 12;
221