• 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 { BaseElement, element } from '../../../../../base-ui/BaseElement';
17import { LitTable } from '../../../../../base-ui/table/lit-table';
18import { SelectionParam } from '../../../../bean/BoxSelection';
19import { log } from '../../../../../log/Log';
20import { PowerDetailsEnergy } from '../../../../bean/EnergyStruct';
21import { SpHiSysEnergyChart } from '../../../chart/SpHiSysEnergyChart';
22import { resizeObserver } from '../SheetUtils';
23import { getTabPowerDetailsData } from '../../../../database/sql/ProcessThread.sql';
24import { TabPanePowerDetailsHTML } from './TabPanePowerDetails.html';
25import { NUM_100, NUM_3 } from '../../../../bean/NumBean';
26
27@element('tabpane-power-details')
28export class TabPanePowerDetails extends BaseElement {
29  private tblPowerDetails: LitTable | null | undefined;
30  private sourcePowerDetails: Array<unknown> = [];
31  private itemType: unknown;
32
33  set data(valPowerDetails: SelectionParam) {
34    this.queryDataByDB(valPowerDetails);
35  }
36
37  connectedCallback(): void {
38    super.connectedCallback();
39    resizeObserver(this.parentElement!, this.tblPowerDetails!);
40  }
41
42  getTimeTypeValue(): string[] {
43    return [
44      'foreground_duration',
45      'background_duration',
46      'screen_on_duration',
47      'screen_off_duration',
48      'foreground_count',
49      'background_count',
50      'screen_on_count',
51      'screen_off_count',
52      'duration',
53      'energy',
54      'usage',
55      'camera_id',
56    ];
57  }
58
59  getDurationTypeValue(): string[] {
60    return [
61      'background_time',
62      'screen_on_time',
63      'screen_off_time',
64      'load',
65      'uid',
66      'usage',
67      'charge',
68      'foreground_count',
69      'background_count',
70      'screen_on_count',
71      'screen_off_count',
72      'energy',
73      'duration',
74    ];
75  }
76
77  getEnergyTypeValue(): string[] {
78    return [
79      'background_time',
80      'screen_on_time',
81      'screen_off_time',
82      'load',
83      'charge',
84      'foreground_count',
85      'background_count',
86      'screen_on_count',
87      'screen_off_count',
88      'camera_id',
89      'uid',
90      'foreground_duration',
91      'foreground_energy',
92      'background_duration',
93      'background_energy',
94      'screen_on_duration',
95      'screen_on_energy',
96      'screen_off_duration',
97      'screen_off_energy',
98    ];
99  }
100
101  getCountTypeValue(): string[] {
102    return [
103      'background_time',
104      'screen_on_time',
105      'screen_off_time',
106      'load',
107      'energy',
108      'usage',
109      'foreground_duration',
110      'background_duration',
111      'screen_on_duration',
112      'screen_off_duration',
113      'camera_id',
114      'uid',
115      'duration',
116      'charge',
117    ];
118  }
119
120  initElements(): void {
121    this.tblPowerDetails = this.shadowRoot?.querySelector<LitTable>('#tb-power-details-energy');
122    this.tblPowerDetails!.addEventListener('column-click', (evt): void => {
123      // @ts-ignore
124      this.sortByColumn(evt.detail);
125    });
126    this.sourcePowerDetails = [];
127    this.itemType = {
128      time_type: [],
129      duration_type: [],
130      energy_type: [],
131      count_type: [],
132    };
133    // @ts-ignore
134    this.itemType.time_type = this.getTimeTypeValue();
135    // @ts-ignore
136    this.itemType.duration_type = this.getDurationTypeValue();
137    // @ts-ignore
138    this.itemType.energy_type = this.getEnergyTypeValue();
139    // @ts-ignore
140    this.itemType.count_type = this.getCountTypeValue();
141  }
142
143  getPowerData(): unknown {
144    return {
145      POWER_IDE_CPU: new PowerDetailsEnergy('CPU'),
146      POWER_IDE_LOCATION: new PowerDetailsEnergy('LOCATION'),
147      POWER_IDE_GPU: new PowerDetailsEnergy('GPU'),
148      POWER_IDE_DISPLAY: new PowerDetailsEnergy('DISPLAY'),
149      POWER_IDE_CAMERA: new PowerDetailsEnergy('CAMERA'),
150      POWER_IDE_BLUETOOTH: new PowerDetailsEnergy('BLUETOOTH'),
151      POWER_IDE_FLASHLIGHT: new PowerDetailsEnergy('FLASHLIGHT'),
152      POWER_IDE_AUDIO: new PowerDetailsEnergy('AUDIO'),
153      POWER_IDE_WIFISCAN: new PowerDetailsEnergy('WIFISCAN'),
154    };
155  }
156
157  getTotalEnergy(powerData: unknown): number {
158    return (
159      // @ts-ignore
160      powerData.POWER_IDE_CPU.getTotalEnergy(false) +
161      // @ts-ignore
162      powerData.POWER_IDE_LOCATION.getTotalEnergy(false) +
163      // @ts-ignore
164      powerData.POWER_IDE_GPU.getTotalEnergy(true) +
165      // @ts-ignore
166      powerData.POWER_IDE_DISPLAY.getTotalEnergy(true) +
167      // @ts-ignore
168      powerData.POWER_IDE_CAMERA.getTotalEnergy(false) +
169      // @ts-ignore
170      powerData.POWER_IDE_BLUETOOTH.getTotalEnergy(false) +
171      // @ts-ignore
172      powerData.POWER_IDE_FLASHLIGHT.getTotalEnergy(false) +
173      // @ts-ignore
174      powerData.POWER_IDE_AUDIO.getTotalEnergy(false) +
175      // @ts-ignore
176      powerData.POWER_IDE_WIFISCAN.getTotalEnergy(false)
177    );
178  }
179
180  queryDataByDB(val: SelectionParam | unknown): void {
181    // @ts-ignore
182    getTabPowerDetailsData(val.leftNs - val.leftNs, val.rightNs).then((items): void => {
183      log(`getTabPowerDetailsData size :${items.length}`);
184      let detailsData: Array<unknown> = [];
185      let set = new Set();
186      set.add('COUNT');
187      set.add('LOAD');
188      set.add('CHARGE');
189      set.add('CAMERA_ID');
190      let powerData: unknown = this.getPowerData();
191      let tsMax = 0;
192      let currentAppIndex = -1;
193      items.forEach((item): void => {
194        // @ts-ignore
195        let powerDatum: unknown = powerData[item.eventName];
196        if (item.appKey.toLocaleLowerCase() === 'appname') {
197          // @ts-ignore
198          powerDatum.appName = SpHiSysEnergyChart.app_name;
199          currentAppIndex = item.eventValue.split(',').indexOf(SpHiSysEnergyChart.app_name!);
200          tsMax = 0;
201        } else if (currentAppIndex > -1 && (set.has(item.appKey) ? item.startNS >= tsMax : true)) {
202          if (set.has(item.appKey)) {
203            // @ts-ignore
204            powerDatum[item.appKey.toLocaleLowerCase()] =
205              item.startNS >= tsMax
206                ? ((tsMax = item.startNS), item.eventValue)
207                : // @ts-ignore
208                  powerDatum[item.appKey.toLocaleLowerCase()];
209          } else {
210            // @ts-ignore
211            powerDatum[item.appKey.toLocaleLowerCase()] =
212              // @ts-ignore
213              (powerDatum[item.appKey.toLocaleLowerCase()] || 0) +
214              parseInt(item.eventValue.split(',')[currentAppIndex]);
215          }
216        }
217      });
218      let totalEnergy = this.getTotalEnergy(powerData);
219      detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_CPU', false, 'time_type'));
220      detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_LOCATION', false, 'duration_type'));
221      detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_GPU', true, 'energy_type'));
222      detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_DISPLAY', true, 'energy_type'));
223      detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_CAMERA', false, 'duration_type'));
224      detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_BLUETOOTH', false, 'duration_type'));
225      detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_FLASHLIGHT', false, 'duration_type'));
226      detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_AUDIO', false, 'duration_type'));
227      detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_WIFISCAN', false, 'count_type'));
228      if (detailsData.length > 0) {
229        this.sourcePowerDetails = detailsData;
230        this.tblPowerDetails!.recycleDataSource = detailsData;
231      } else {
232        this.sourcePowerDetails = [];
233        this.tblPowerDetails!.recycleDataSource = [];
234      }
235      this.updateTableStyles();
236    });
237    let th = this.tblPowerDetails?.shadowRoot?.querySelector<HTMLDivElement>('.th');
238    if (th) {
239      th!.style.gridColumnGap = '5px';
240    }
241  }
242
243  updateTableStyles(): void {
244    this.tblPowerDetails?.shadowRoot?.querySelectorAll<HTMLDivElement>('.td').forEach((td): void => {
245      td.style.fontSize = '14px';
246      td.style.fontWeight = '400';
247      td.style.opacity = '0.9';
248      td.style.lineHeight = '16px';
249    });
250  }
251
252  setEnergyItems(
253    powerData: unknown,
254    totalEnergy: number,
255    energyName: string,
256    isSimpleEnergy: boolean,
257    type: unknown
258  ): unknown {
259    // @ts-ignore
260    let ratio = (powerData[energyName].getTotalEnergy(isSimpleEnergy) * NUM_100) / totalEnergy;
261    if (totalEnergy === 0) {
262      // @ts-ignore
263      powerData[energyName].energyConsumptionRatio = '0.000 %';
264    } else {
265      // @ts-ignore
266      powerData[energyName].energyConsumptionRatio = `${ratio.toFixed(NUM_3)} %`;
267    }
268    return this.getEnergyStyle(powerData, energyName, type);
269  }
270
271  getEnergyStyle(powerData: unknown, energyName: string, type: unknown): unknown {
272    // @ts-ignore
273    this.itemType[type].forEach((item: unknown): void => {
274      // @ts-ignore
275      powerData[energyName][item] = '-';
276    });
277    if (type === 'energy_type') {
278      if (energyName === 'POWER_IDE_GPU') {
279        // @ts-ignore
280        powerData[energyName].duration = '-';
281      } else {
282        // @ts-ignore
283        powerData[energyName].usage = '-';
284      }
285    } else if (type === 'duration_type') {
286      if (energyName !== 'POWER_IDE_CAMERA') {
287        // @ts-ignore
288        powerData[energyName].camera_id = '-';
289      }
290    }
291    // @ts-ignore
292    return powerData[energyName];
293  }
294
295  initHtml(): string {
296    return TabPanePowerDetailsHTML;
297  }
298
299  sortByColumn(detail: unknown): void {
300    // @ts-ignore
301    function compare(property, sort, type) {
302      return function (aPowerDetails: PowerDetailsEnergy, bPowerDetails: PowerDetailsEnergy) {
303        if (type === 'number') {
304          return sort === 2 // @ts-ignore
305            ? parseFloat(bPowerDetails[property] === '-' ? 0 : bPowerDetails[property]) - // @ts-ignore
306                parseFloat(aPowerDetails[property] === '-' ? 0 : aPowerDetails[property]) // @ts-ignore
307            : parseFloat(aPowerDetails[property] === '-' ? 0 : aPowerDetails[property]) - // @ts-ignore
308                parseFloat(bPowerDetails[property] === '-' ? 0 : bPowerDetails[property]);
309        } else {
310          // @ts-ignore
311          if (bPowerDetails[property] > aPowerDetails[property]) {
312            return sort === 2 ? 1 : -1;
313          } else {
314            // @ts-ignore
315            if (bPowerDetails[property] === aPowerDetails[property]) {
316              return 0;
317            } else {
318              return sort === 2 ? -1 : 1;
319            }
320          }
321        }
322      };
323    }
324    // @ts-ignore
325    if (detail.key === 'appName') {
326      // @ts-ignore
327      this.sourcePowerDetails.sort(compare(detail.key, detail.sort, 'string'));
328    } else {
329      // @ts-ignore
330      this.sourcePowerDetails.sort(compare(detail.key, detail.sort, 'number'));
331    }
332    this.tblPowerDetails!.recycleDataSource = this.sourcePowerDetails;
333
334    this.tblPowerDetails?.shadowRoot?.querySelectorAll<HTMLDivElement>('.td').forEach((td): void => {
335      td.style.fontSize = '14px';
336      td.style.fontWeight = '400';
337      td.style.opacity = '0.9';
338      td.style.lineHeight = '16px';
339    });
340  }
341}
342