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<any> = []; 31 private itemType: any; 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) => { 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 this.itemType.time_type = this.getTimeTypeValue(); 134 this.itemType.duration_type = this.getDurationTypeValue(); 135 this.itemType.energy_type = this.getEnergyTypeValue(); 136 this.itemType.count_type = this.getCountTypeValue(); 137 } 138 139 getPowerData() { 140 return { 141 POWER_IDE_CPU: new PowerDetailsEnergy('CPU'), 142 POWER_IDE_LOCATION: new PowerDetailsEnergy('LOCATION'), 143 POWER_IDE_GPU: new PowerDetailsEnergy('GPU'), 144 POWER_IDE_DISPLAY: new PowerDetailsEnergy('DISPLAY'), 145 POWER_IDE_CAMERA: new PowerDetailsEnergy('CAMERA'), 146 POWER_IDE_BLUETOOTH: new PowerDetailsEnergy('BLUETOOTH'), 147 POWER_IDE_FLASHLIGHT: new PowerDetailsEnergy('FLASHLIGHT'), 148 POWER_IDE_AUDIO: new PowerDetailsEnergy('AUDIO'), 149 POWER_IDE_WIFISCAN: new PowerDetailsEnergy('WIFISCAN'), 150 }; 151 } 152 153 getTotalEnergy(powerData: any) { 154 return powerData.POWER_IDE_CPU.getTotalEnergy(false) + 155 powerData.POWER_IDE_LOCATION.getTotalEnergy(false) + 156 powerData.POWER_IDE_GPU.getTotalEnergy(true) + 157 powerData.POWER_IDE_DISPLAY.getTotalEnergy(true) + 158 powerData.POWER_IDE_CAMERA.getTotalEnergy(false) + 159 powerData.POWER_IDE_BLUETOOTH.getTotalEnergy(false) + 160 powerData.POWER_IDE_FLASHLIGHT.getTotalEnergy(false) + 161 powerData.POWER_IDE_AUDIO.getTotalEnergy(false) + 162 powerData.POWER_IDE_WIFISCAN.getTotalEnergy(false); 163 } 164 165 queryDataByDB(val: SelectionParam | any): void { 166 getTabPowerDetailsData(val.leftNs - val.leftNs, val.rightNs).then((items) => { 167 log('getTabPowerDetailsData size :' + items.length); 168 let detailsData: Array<any> = []; 169 let set = new Set(); 170 set.add('COUNT'); 171 set.add('LOAD'); 172 set.add('CHARGE'); 173 set.add('CAMERA_ID'); 174 let powerData: any = this.getPowerData(); 175 let tsMax = 0; 176 let currentAppIndex = -1; 177 items.forEach((item) => { 178 let powerDatum: any = powerData[item.eventName]; 179 if (item.appKey.toLocaleLowerCase() === 'appname') { 180 powerDatum.appName = SpHiSysEnergyChart.app_name; 181 currentAppIndex = item.eventValue.split(',').indexOf(SpHiSysEnergyChart.app_name!); 182 tsMax = 0; 183 } else if (currentAppIndex > -1 && (set.has(item.appKey) ? item.startNS >= tsMax : true)) { 184 if (set.has(item.appKey)) { 185 powerDatum[item.appKey.toLocaleLowerCase()] = item.startNS >= tsMax ? (tsMax = item.startNS , item.eventValue) : powerDatum[item.appKey.toLocaleLowerCase()]; 186 } else { 187 powerDatum[item.appKey.toLocaleLowerCase()] = (powerDatum[item.appKey.toLocaleLowerCase()] || 0) + parseInt(item.eventValue.split(',')[currentAppIndex]); 188 } 189 } 190 }); 191 let totalEnergy = this.getTotalEnergy(powerData); 192 detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_CPU', false, 'time_type')); 193 detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_LOCATION', false, 'duration_type')); 194 detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_GPU', true, 'energy_type')); 195 detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_DISPLAY', true, 'energy_type')); 196 detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_CAMERA', false, 'duration_type')); 197 detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_BLUETOOTH', false, 'duration_type')); 198 detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_FLASHLIGHT', false, 'duration_type')); 199 detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_AUDIO', false, 'duration_type')); 200 detailsData.push(this.setEnergyItems(powerData, totalEnergy, 'POWER_IDE_WIFISCAN', false, 'count_type')); 201 if (detailsData.length > 0) { 202 this.sourcePowerDetails = detailsData; 203 this.tblPowerDetails!.recycleDataSource = detailsData; 204 } else { 205 this.sourcePowerDetails = []; 206 this.tblPowerDetails!.recycleDataSource = []; 207 } 208 this.updateTableStyles(); 209 }); 210 let th = this.tblPowerDetails?.shadowRoot?.querySelector<HTMLDivElement>('.th'); 211 if (th) { 212 th!.style.gridColumnGap = '5px'; 213 } 214 } 215 216 updateTableStyles() { 217 this.tblPowerDetails?.shadowRoot?.querySelectorAll<HTMLDivElement>('.td').forEach((td) => { 218 td.style.fontSize = '14px'; 219 td.style.fontWeight = '400'; 220 td.style.opacity = '0.9'; 221 td.style.lineHeight = '16px'; 222 }); 223 } 224 225 setEnergyItems(powerData: any, totalEnergy: number, energyName: string, isSimpleEnergy: boolean, type: any): any { 226 let ratio = (powerData[energyName].getTotalEnergy(isSimpleEnergy) * NUM_100) / totalEnergy; 227 if (totalEnergy === 0) { 228 powerData[energyName].energyConsumptionRatio = '0.000 %'; 229 } else { 230 powerData[energyName].energyConsumptionRatio = ratio.toFixed(NUM_3) + ' %'; 231 } 232 return this.getEnergyStyle(powerData, energyName, type); 233 } 234 235 getEnergyStyle(powerData: any, energyName: string, type: any) { 236 this.itemType[type].forEach((item: any) => { 237 powerData[energyName][item] = '-'; 238 }); 239 if (type === 'energy_type') { 240 if (energyName === 'POWER_IDE_GPU') { 241 powerData[energyName]['duration'] = '-'; 242 } else { 243 powerData[energyName]['usage'] = '-'; 244 } 245 } else if (type === 'duration_type') { 246 if (energyName !== 'POWER_IDE_CAMERA') { 247 powerData[energyName]['camera_id'] = '-'; 248 } 249 } 250 return powerData[energyName]; 251 } 252 253 initHtml(): string { 254 return TabPanePowerDetailsHTML; 255 } 256 257 sortByColumn(detail: any): void { 258 // @ts-ignore 259 function compare(property, sort, type) { 260 return function (aPowerDetails: PowerDetailsEnergy, bPowerDetails: PowerDetailsEnergy) { 261 if (type === 'number') { 262 return sort === 2 263 ? // @ts-ignore 264 parseFloat(bPowerDetails[property] === '-' ? 0 : bPowerDetails[property]) - 265 // @ts-ignore 266 parseFloat(aPowerDetails[property] === '-' ? 0 : aPowerDetails[property]) 267 : // @ts-ignore 268 parseFloat(aPowerDetails[property] === '-' ? 0 : aPowerDetails[property]) - 269 // @ts-ignore 270 parseFloat(bPowerDetails[property] === '-' ? 0 : bPowerDetails[property]); 271 } else { 272 // @ts-ignore 273 if (bPowerDetails[property] > aPowerDetails[property]) { 274 return sort === 2 ? 1 : -1; 275 } else { 276 // @ts-ignore 277 if (bPowerDetails[property] === aPowerDetails[property]) { 278 return 0; 279 } else { 280 return sort === 2 ? -1 : 1; 281 } 282 } 283 } 284 }; 285 } 286 287 if (detail.key === 'appName') { 288 this.sourcePowerDetails.sort(compare(detail.key, detail.sort, 'string')); 289 } else { 290 this.sourcePowerDetails.sort(compare(detail.key, detail.sort, 'number')); 291 } 292 this.tblPowerDetails!.recycleDataSource = this.sourcePowerDetails; 293 294 this.tblPowerDetails?.shadowRoot?.querySelectorAll<HTMLDivElement>('.td').forEach((td) => { 295 td.style.fontSize = '14px'; 296 td.style.fontWeight = '400'; 297 td.style.opacity = '0.9'; 298 td.style.lineHeight = '16px'; 299 }); 300 } 301} 302