• 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 {
17  BaseStruct,
18  drawLines,
19  drawLoading,
20  drawFlagLine,
21  drawSelection,
22  isFrameContainPoint,
23  ns2x,
24  Render,
25  RequestMessage,
26} from './ProcedureWorkerCommon.js';
27import { TraceRow } from '../../component/trace/base/TraceRow.js';
28
29export class EnergyStateRender extends Render {
30  renderMainThread(
31    req: {
32      useCache: boolean;
33      context: CanvasRenderingContext2D;
34      type: string;
35      maxState: number;
36      maxStateName: string;
37    },
38    row: TraceRow<EnergyStateStruct>
39  ) {
40    let stateList = row.dataList;
41    let stateFilter = row.dataListCache;
42    state(
43      stateList,
44      stateFilter,
45      TraceRow.range!.startNS,
46      TraceRow.range!.endNS,
47      TraceRow.range!.totalNS,
48      row.frame,
49      req.useCache || !TraceRow.range!.refresh
50    );
51    req.context.beginPath();
52    let find = false;
53    for (let i = 0; i < stateFilter.length; i++) {
54      let re = stateFilter[i];
55      EnergyStateStruct.draw(req.context, re, req.maxState, req.maxStateName);
56      if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) {
57        EnergyStateStruct.hoverEnergyStateStruct = re;
58        find = true;
59      }
60    }
61    if (!find && row.isHover) EnergyStateStruct.hoverEnergyStateStruct = undefined;
62    if (req.maxStateName != 'enable' && req.maxStateName != 'disable' && req.maxStateName != '-1') {
63      let s = req.maxStateName;
64      let textMetrics = req.context.measureText(s);
65      req.context.globalAlpha = 1.0;
66      req.context.fillStyle = '#f0f0f0';
67      req.context.fillRect(0, 5, textMetrics.width + 8, 18);
68      req.context.fillStyle = '#333';
69      req.context.textBaseline = 'middle';
70      req.context.fillText(s, 4, 5 + 9);
71    }
72    req.context.closePath();
73  }
74
75  render(energyStateRequest: RequestMessage, stateList: Array<any>, filter: Array<any>) {
76    if (energyStateRequest.lazyRefresh) {
77      state(
78        stateList,
79        filter,
80        energyStateRequest.startNS,
81        energyStateRequest.endNS,
82        energyStateRequest.totalNS,
83        energyStateRequest.frame,
84        energyStateRequest.useCache || !energyStateRequest.range.refresh
85      );
86    } else {
87      if (!energyStateRequest.useCache) {
88        state(
89          stateList,
90          filter,
91          energyStateRequest.startNS,
92          energyStateRequest.endNS,
93          energyStateRequest.totalNS,
94          energyStateRequest.frame,
95          false
96        );
97      }
98    }
99    if (energyStateRequest.canvas) {
100      energyStateRequest.context.clearRect(0, 0, energyStateRequest.canvas.width, energyStateRequest.canvas.height);
101      let energyStateArr = filter;
102      if (
103        energyStateArr.length > 0 &&
104        !energyStateRequest.range.refresh &&
105        !energyStateRequest.useCache &&
106        energyStateRequest.lazyRefresh
107      ) {
108        drawLoading(
109          energyStateRequest.context,
110          energyStateRequest.startNS,
111          energyStateRequest.endNS,
112          energyStateRequest.totalNS,
113          energyStateRequest.frame,
114          energyStateArr[0].startNS,
115          energyStateArr[energyStateArr.length - 1].startNS + energyStateArr[energyStateArr.length - 1].dur
116        );
117      }
118      drawLines(
119        energyStateRequest.context,
120        energyStateRequest.xs,
121        energyStateRequest.frame.height,
122        energyStateRequest.lineColor
123      );
124      energyStateRequest.context.beginPath();
125      EnergyStateStruct.maxState = energyStateRequest.params.maxState;
126      EnergyStateStruct.maxStateName = energyStateRequest.params.maxStateName;
127      drawLines(
128        energyStateRequest.context,
129        energyStateRequest.xs,
130        energyStateRequest.frame.height,
131        energyStateRequest.lineColor
132      );
133      EnergyStateStruct.hoverEnergyStateStruct = undefined;
134      if (energyStateRequest.isHover) {
135        for (let re of filter) {
136          if (
137            re.frame &&
138            energyStateRequest.hoverX >= re.frame.x &&
139            energyStateRequest.hoverX <= re.frame.x + re.frame.width &&
140            energyStateRequest.hoverY >= re.frame.y &&
141            energyStateRequest.hoverY <= re.frame.y + re.frame.height
142          ) {
143            EnergyStateStruct.hoverEnergyStateStruct = re;
144            break;
145          }
146        }
147      }
148      EnergyStateStruct.selectEnergyStateStruct = energyStateRequest.params.selectEnergyStateStruct;
149      for (let re of filter) {
150        EnergyStateStruct.draw(energyStateRequest.context, re, 0, '');
151      }
152      drawSelection(energyStateRequest.context, energyStateRequest.params);
153      energyStateRequest.context.closePath();
154      if (
155        EnergyStateStruct.maxStateName != 'enable' &&
156        EnergyStateStruct.maxStateName != 'disable' &&
157        EnergyStateStruct.maxStateName != '-1'
158      ) {
159        let s = EnergyStateStruct.maxStateName;
160        let textMetrics = energyStateRequest.context.measureText(s);
161        energyStateRequest.context.globalAlpha = 1.0;
162        energyStateRequest.context.fillStyle = '#f0f0f0';
163        energyStateRequest.context.fillRect(0, 5, textMetrics.width + 8, 18);
164        energyStateRequest.context.fillStyle = '#333';
165        energyStateRequest.context.textBaseline = 'middle';
166        energyStateRequest.context.fillText(s, 4, 5 + 9);
167      }
168      drawFlagLine(
169        energyStateRequest.context,
170        energyStateRequest.flagMoveInfo,
171        energyStateRequest.flagSelectedInfo,
172        energyStateRequest.startNS,
173        energyStateRequest.endNS,
174        energyStateRequest.totalNS,
175        energyStateRequest.frame,
176        energyStateRequest.slicesTime
177      );
178    }
179    // @ts-ignore
180    self.postMessage({
181      id: energyStateRequest.id,
182      type: energyStateRequest.type,
183      results: energyStateRequest.canvas ? undefined : filter,
184      hover: EnergyStateStruct.hoverEnergyStateStruct,
185    });
186  }
187}
188
189export function state(
190  stateList: Array<any>,
191  res: Array<any>,
192  startNS: number,
193  endNS: number,
194  totalNS: number,
195  frame: any,
196  use: boolean
197) {
198  if (use && res.length > 0) {
199    for (let i = 0; i < res.length; i++) {
200      let stateItem = res[i];
201      if ((stateItem.startNs || 0) + (stateItem.dur || 0) > (startNS || 0) && (stateItem.startNs || 0) < (endNS || 0)) {
202        EnergyStateStruct.setStateFrame(stateItem, 5, startNS || 0, endNS || 0, totalNS || 0, frame);
203      } else {
204        stateItem.frame = null;
205      }
206    }
207    return;
208  }
209  res.length = 0;
210  if (stateList) {
211    for (let index = 0; index < stateList.length; index++) {
212      let item = stateList[index];
213      if (index === stateList.length - 1) {
214        item.dur = (endNS || 0) - (item.startNs || 0);
215      } else {
216        item.dur = (stateList[index + 1].startNs || 0) - (item.startNs || 0);
217      }
218      if ((item.startNs || 0) + (item.dur || 0) > (startNS || 0) && (item.startNs || 0) < (endNS || 0)) {
219        EnergyStateStruct.setStateFrame(stateList[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame);
220        if (
221          index > 0 &&
222          (stateList[index - 1].frame?.x || 0) == (stateList[index].frame?.x || 0) &&
223          (stateList[index - 1].frame?.width || 0) == (stateList[index].frame?.width || 0)
224        ) {
225        } else {
226          res.push(item);
227        }
228      }
229    }
230  }
231}
232
233export class EnergyStateStruct extends BaseStruct {
234  static maxState: number = 0;
235  static maxStateName: string = '0';
236  static hoverEnergyStateStruct: EnergyStateStruct | undefined;
237  static selectEnergyStateStruct: EnergyStateStruct | undefined;
238  type: string | undefined;
239  value: number | undefined;
240  startNs: number | undefined;
241  dur: number | undefined;
242
243  sensorType: number | undefined;
244  pkg_name: string | undefined;
245  deviceState: number | undefined;
246  deviceType: number | undefined;
247
248  static draw(
249    energyStateContext: CanvasRenderingContext2D,
250    data: EnergyStateStruct,
251    maxState: number,
252    maxStateName: string
253  ) {
254    if (data.frame) {
255      let width = data.frame.width || 0;
256      let drawColor = this.setDrawColor(data.type!);
257      energyStateContext.fillStyle = drawColor;
258      energyStateContext.strokeStyle = drawColor;
259      energyStateContext.globalAlpha = 1.0;
260      energyStateContext.lineWidth = 1;
261      let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxState);
262      if (maxStateName === 'enable' || maxStateName === 'disable') {
263        if (data.value == 0) {
264          drawHeight = data.frame.height;
265          energyStateContext.fillRect(data.frame.x, data.frame.y + 4, width, data.frame.height);
266        }
267      } else {
268        energyStateContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight);
269      }
270      if (data.startNs === EnergyStateStruct.hoverEnergyStateStruct?.startNs) {
271        let pointy = data.frame.y + data.frame.height + 4;
272        if (data.value == 0) {
273          pointy -= drawHeight;
274        }
275        energyStateContext.beginPath();
276        energyStateContext.arc(data.frame.x, pointy, 3, 0, 2 * Math.PI, true);
277        energyStateContext.fill();
278        energyStateContext.globalAlpha = 1.0;
279        energyStateContext.stroke();
280        energyStateContext.beginPath();
281        energyStateContext.moveTo(data.frame.x + 3, pointy);
282        energyStateContext.lineWidth = 3;
283        energyStateContext.lineTo(data.frame.x + width, pointy);
284        energyStateContext.stroke();
285      }
286    }
287    energyStateContext.globalAlpha = 1.0;
288    energyStateContext.lineWidth = 1;
289  }
290
291  static setStateFrame(stateNode: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) {
292    let stateStartPointX: number, stateEndPointX: number;
293
294    if ((stateNode.startNs || 0) < startNS) {
295      stateStartPointX = 0;
296    } else {
297      stateStartPointX = ns2x(stateNode.startNs || 0, startNS, endNS, totalNS, frame);
298    }
299    if ((stateNode.startNs || 0) + (stateNode.dur || 0) > endNS) {
300      stateEndPointX = frame.width;
301    } else {
302      stateEndPointX = ns2x((stateNode.startNs || 0) + (stateNode.dur || 0), startNS, endNS, totalNS, frame);
303    }
304    let frameWidth: number = stateEndPointX - stateStartPointX <= 1 ? 1 : stateEndPointX - stateStartPointX;
305    if (!stateNode.frame) {
306      stateNode.frame = {};
307    }
308    stateNode.frame.x = Math.floor(stateStartPointX);
309    stateNode.frame.y = frame.y + padding;
310    stateNode.frame.width = Math.ceil(frameWidth);
311    stateNode.frame.height = Math.floor(frame.height - padding * 2);
312  }
313
314  static setDrawColor(eventType: string): string {
315    switch (eventType) {
316      case 'BRIGHTNESS_NIT':
317        return '#92D6CC';
318      case 'SIGNAL_LEVEL':
319        return '#61CFBE';
320      case 'WIFI_EVENT_RECEIVED':
321        return '#46B1E3';
322      case 'AUDIO_STREAM_CHANGE':
323        return '#ED6F21';
324      case 'WIFI_STATE':
325        return '#61CFBE';
326      case 'LOCATION_SWITCH_STATE':
327        return '#61CFBE';
328      case 'SENSOR_STATE':
329        return '#61CFBE';
330      default:
331        return '#61CFBE';
332    }
333  }
334}
335