• 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 { BaseStruct, isFrameContainPoint, drawLoadingFrame, ns2x, Render, Rect } from './ProcedureWorkerCommon';
17import { TraceRow } from '../../component/trace/base/TraceRow';
18
19export class EnergyStateRender extends Render {
20  renderMainThread(
21    req: {
22      useCache: boolean;
23      context: CanvasRenderingContext2D;
24      type: string;
25      maxState: number;
26      maxStateName: string;
27    },
28    row: TraceRow<EnergyStateStruct>
29  ): void {
30    let stateList = row.dataList;
31    let stateFilter = row.dataListCache;
32    state(
33      stateList,
34      stateFilter,
35      TraceRow.range!.startNS || 0,
36      TraceRow.range!.endNS || 0,
37      TraceRow.range!.totalNS || 0,
38      row.frame,
39      req.useCache || !TraceRow.range!.refresh
40    );
41    drawLoadingFrame(req.context, row.dataListCache, row);
42    req.context.beginPath();
43    let find = false;
44    for (let i = 0; i < stateFilter.length; i++) {
45      let re = stateFilter[i];
46      EnergyStateStruct.draw(req.context, re, req.maxState, req.maxStateName);
47      if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) {
48        EnergyStateStruct.hoverEnergyStateStruct = re;
49        find = true;
50      }
51    }
52    if (!find && row.isHover) {
53      EnergyStateStruct.hoverEnergyStateStruct = undefined;
54    }
55    if (req.maxStateName !== 'enable' && req.maxStateName !== 'disable' && req.maxStateName !== '-1') {
56      let s = req.maxStateName;
57      let textMetrics = req.context.measureText(s);
58      req.context.globalAlpha = 1.0;
59      req.context.fillStyle = '#f0f0f0';
60      req.context.fillRect(0, 5, textMetrics.width + 8, 18);
61      req.context.fillStyle = '#333';
62      req.context.textBaseline = 'middle';
63      req.context.fillText(s, 4, 5 + 9);
64    }
65    req.context.closePath();
66  }
67}
68
69export function state(
70  stateList: Array<EnergyStateStruct>,
71  res: Array<EnergyStateStruct>,
72  startNS: number,
73  endNS: number,
74  totalNS: number,
75  frame: Rect,
76  use: boolean
77): void {
78  if (use && res.length > 0) {
79    for (let i = 0; i < res.length; i++) {
80      let stateItem = res[i];
81      if (i === res.length - 1) {
82        stateItem.dur = endNS - (stateItem.startNs || 0);
83      } else {
84        stateItem.dur = (res[i + 1].startNs || 0) - (stateItem.startNs || 0);
85      }
86      if ((stateItem.startNs || 0) + (stateItem.dur || 0) > startNS && (stateItem.startNs || 0) < endNS) {
87        EnergyStateStruct.setStateFrame(res[i], 5, startNS, endNS, totalNS, frame);
88      }
89    }
90    return;
91  }
92  res.length = 0;
93  stateFilter(stateList, startNS, endNS, totalNS, frame, res);
94}
95function stateFilter(
96  stateList: Array<EnergyStateStruct>,
97  startNS: number,
98  endNS: number,
99  totalNS: number,
100  frame: Rect,
101  res: Array<EnergyStateStruct>
102): void {
103  if (stateList) {
104    for (let index = 0; index < stateList.length; index++) {
105      let item = stateList[index];
106      item.dur =
107        index === stateList.length - 1
108          ? endNS - (item.startNs || 0)
109          : (stateList[index + 1].startNs || 0) - (item.startNs || 0);
110      if ((item.startNs || 0) + (item.dur || 0) > startNS && (item.startNs || 0) < endNS) {
111        EnergyStateStruct.setStateFrame(stateList[index], 5, startNS, endNS, totalNS, frame);
112        if (
113          !(
114            index > 0 &&
115            (stateList[index - 1].frame?.x || 0) === (stateList[index].frame?.x || 0) &&
116            (stateList[index - 1].frame?.width || 0) === (stateList[index].frame?.width || 0)
117          )
118        ) {
119          res.push(item);
120        }
121      }
122    }
123  }
124}
125
126export class EnergyStateStruct extends BaseStruct {
127  static maxState: number = 0;
128  static maxStateName: string = '0';
129  static hoverEnergyStateStruct: EnergyStateStruct | undefined;
130  static selectEnergyStateStruct: EnergyStateStruct | undefined;
131  type: string | undefined;
132  value: number | undefined;
133  startNs: number | undefined;
134  dur: number | undefined;
135
136  sensorType: number | undefined;
137  pkg_name: string | undefined;
138  deviceState: number | undefined;
139  deviceType: number | undefined;
140
141  static draw(
142    energyStateContext: CanvasRenderingContext2D,
143    data: EnergyStateStruct,
144    maxState: number,
145    maxStateName: string
146  ): void {
147    if (data.frame) {
148      let width = data.frame.width || 0;
149      let drawColor = this.setDrawColor(data.type!);
150      energyStateContext.fillStyle = drawColor;
151      energyStateContext.strokeStyle = drawColor;
152      energyStateContext.globalAlpha = 1.0;
153      energyStateContext.lineWidth = 1;
154      let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxState);
155      if (maxStateName === 'enable' || maxStateName === 'disable') {
156        if (data.value === 0) {
157          drawHeight = data.frame.height;
158          energyStateContext.fillRect(data.frame.x, data.frame.y + 4, width, data.frame.height);
159        }
160      } else {
161        energyStateContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight + 4, width, drawHeight);
162      }
163      if (data.startNs === EnergyStateStruct.hoverEnergyStateStruct?.startNs) {
164        let pointy = data.frame.y + data.frame.height + 4;
165        if (data.value === 0) {
166          pointy -= drawHeight;
167        }
168        energyStateContext.beginPath();
169        energyStateContext.arc(data.frame.x, pointy, 3, 0, 2 * Math.PI, true);
170        energyStateContext.fill();
171        energyStateContext.globalAlpha = 1.0;
172        energyStateContext.stroke();
173        energyStateContext.beginPath();
174        energyStateContext.moveTo(data.frame.x + 3, pointy);
175        energyStateContext.lineWidth = 3;
176        energyStateContext.lineTo(data.frame.x + width, pointy);
177        energyStateContext.stroke();
178      }
179    }
180    energyStateContext.globalAlpha = 1.0;
181    energyStateContext.lineWidth = 1;
182  }
183
184  static setStateFrame(
185    stateNode: EnergyStateStruct,
186    padding: number,
187    startNS: number,
188    endNS: number,
189    totalNS: number,
190    frame: Rect
191  ): void {
192    let stateStartPointX: number;
193    let stateEndPointX: number;
194
195    if ((stateNode.startNs || 0) < startNS) {
196      stateStartPointX = 0;
197    } else {
198      stateStartPointX = ns2x(stateNode.startNs || 0, startNS, endNS, totalNS, frame);
199    }
200    if ((stateNode.startNs || 0) + (stateNode.dur || 0) > endNS) {
201      stateEndPointX = frame.width;
202    } else {
203      stateEndPointX = ns2x((stateNode.startNs || 0) + (stateNode.dur || 0), startNS, endNS, totalNS, frame);
204    }
205    let frameWidth: number = stateEndPointX - stateStartPointX <= 1 ? 1 : stateEndPointX - stateStartPointX;
206    if (!stateNode.frame) {
207      stateNode.frame = new Rect(0, 0, 0, 0);
208    }
209    stateNode.frame.x = Math.floor(stateStartPointX);
210    stateNode.frame.y = frame.y + padding;
211    stateNode.frame.width = Math.ceil(frameWidth);
212    stateNode.frame.height = Math.floor(frame.height - padding * 2);
213  }
214
215  static setDrawColor(eventType: string): string {
216    switch (eventType) {
217      case 'BRIGHTNESS_NIT':
218        return '#92D6CC';
219      case 'SIGNAL_LEVEL':
220        return '#61CFBE';
221      case 'WIFI_EVENT_RECEIVED':
222        return '#46B1E3';
223      case 'AUDIO_STREAM_CHANGE':
224        return '#ED6F21';
225      case 'WIFI_STATE':
226        return '#61CFBE';
227      case 'LOCATION_SWITCH_STATE':
228        return '#61CFBE';
229      case 'SENSOR_STATE':
230        return '#61CFBE';
231      default:
232        return '#61CFBE';
233    }
234  }
235}
236