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 { TraficEnum } from './utils/QueryEnum'; 17import { energyList } from './utils/AllMemoryCache'; 18import { Args } from './CommonArgs'; 19 20export const systemDataSql = (args: Args): string => { 21 return `SELECT S.id, 22 S.ts - ${args.recordStartNS 23 } AS startNs, 24 D.data AS eventName, 25 (case when D.data = 'POWER_RUNNINGLOCK' then 1 when D.data = 'GNSS_STATE' then 2 else 0 end) AS appKey, 26 contents AS eventValue, 27 ((S.ts - ${args.recordStartNS}) / (${Math.floor((args.endNS - args.startNS) / args.width)})) as px 28 FROM hisys_all_event AS S 29 LEFT JOIN data_dict AS D ON S.event_name_id = D.id 30 LEFT JOIN data_dict AS D2 ON S.domain_id = D2.id 31 WHERE eventName IN ('POWER_RUNNINGLOCK', 'GNSS_STATE', 'WORK_START', 'WORK_REMOVE', 'WORK_STOP', 'WORK_ADD') 32 and startNs >= ${Math.floor(args.startNS)} 33 and startNs <= ${Math.floor(args.endNS)} 34 group by px;`; 35}; 36 37export const systemDataMemSql = (args: Args): string => { 38 return `SELECT S.id, 39 S.ts - ${args.recordStartNS} AS startNs, 40 D.data AS eventName, 41 (case when D.data = 'POWER_RUNNINGLOCK' then '1' when D.data = 'GNSS_STATE' then '2' else '0' end) AS appKey, 42 contents AS eventValue 43 FROM hisys_all_event AS S 44 LEFT JOIN data_dict AS D ON S.event_name_id = D.id 45 LEFT JOIN data_dict AS D2 ON S.domain_id = D2.id 46 WHERE eventName IN 47 ('POWER_RUNNINGLOCK', 'GNSS_STATE', 'WORK_START', 'WORK_REMOVE', 'WORK_STOP', 'WORK_ADD');`; 48}; 49 50export const chartEnergyAnomalyDataSql = (args: Args): string => { 51 return ` 52 select S.id, 53 S.ts - ${args.recordStartNS} as startNs, 54 D.data as eventName, 55 D2.data as appKey, 56 (case 57 when S.type==1 then group_concat(S.string_value, ',') 58 else group_concat(S.int_value, ',') end) as eventValue 59 from hisys_event_measure as S 60 left join data_dict as D 61 on D.id = S.name_id 62 left join app_name as APP on APP.id = S.key_id 63 left join data_dict as D2 on D2.id = APP.app_key 64 where D.data in 65 ('ANOMALY_SCREEN_OFF_ENERGY', 'ANOMALY_KERNEL_WAKELOCK', 'ANOMALY_CPU_HIGH_FREQUENCY', 'ANOMALY_WAKEUP') 66 or (D.data in ('ANOMALY_RUNNINGLOCK', 'ANORMALY_APP_ENERGY', 'ANOMALY_GNSS_ENERGY', 'ANOMALY_CPU_ENERGY', 67 'ANOMALY_ALARM_WAKEUP') 68 and D2.data in ('APPNAME')) 69 group by S.serial, D.data`; 70}; 71export const queryPowerValueSql = (args: Args): string => { 72 return ` 73 SELECT S.id, 74 S.ts - ${args.recordStartNS} as startNs, 75 D.data AS eventName, 76 D2.data AS appKey, 77 group_concat((CASE WHEN S.type = 1 THEN S.string_value ELSE S.int_value END), ',') AS eventValue 78 FROM hisys_event_measure AS S 79 LEFT JOIN data_dict AS D 80 ON D.id = S.name_id 81 LEFT JOIN app_name AS APP 82 ON APP.id = S.key_id 83 LEFT JOIN data_dict AS D2 84 ON D2.id = APP.app_key 85 where D.data in ('POWER_IDE_CPU', 'POWER_IDE_LOCATION', 'POWER_IDE_GPU', 'POWER_IDE_DISPLAY', 'POWER_IDE_CAMERA', 86 'POWER_IDE_BLUETOOTH', 'POWER_IDE_FLASHLIGHT', 'POWER_IDE_AUDIO', 'POWER_IDE_WIFISCAN') 87 and D2.data in 88 ('BACKGROUND_ENERGY', 'FOREGROUND_ENERGY', 'SCREEN_ON_ENERGY', 'SCREEN_OFF_ENERGY', 'ENERGY', 'APPNAME') 89 GROUP BY S.serial, 90 APP.app_key, 91 D.data, 92 D2.data 93 ORDER BY eventName;`; 94}; 95 96export const queryStateDataSql = (args: Args): string => { 97 return ` 98 select S.id, 99 S.ts - ${args.recordStartNS} as startNs, 100 D.data as eventName, 101 D2.data as appKey, 102 S.int_value as eventValue 103 from hisys_event_measure as S 104 left join data_dict as D on D.id = S.name_id 105 left join app_name as APP on APP.id = S.key_id 106 left join data_dict as D2 on D2.id = APP.app_key 107 where (case when 'SENSOR_STATE'== '${args.eventName}' then D.data like '%SENSOR%' else D.data = '${args.eventName}' end) 108 and D2.data in ('BRIGHTNESS', 'STATE', 'VALUE', 'LEVEL', 'VOLUME', 'OPER_TYPE', 'VOLUME') 109 group by S.serial, APP.app_key, D.data, D2.data;`; 110}; 111 112export const queryStateProtoDataSql = (args: Args): string => { 113 return ` 114 SELECT S.id, 115 S.ts - ${args.recordStartNS} AS startNs, 116 D.data AS eventName, 117 '' AS appKey, 118 contents AS eventValue 119 FROM hisys_all_event AS S 120 LEFT JOIN data_dict AS D ON S.event_name_id = D.id 121 LEFT JOIN data_dict AS D2 ON S.domain_id = D2.id 122 WHERE eventName = ${args.eventName}`; 123}; 124let systemList: Array<unknown> = []; 125let anomalyList: Array<unknown> = []; 126let powerList: Array<unknown> = []; 127 128export function resetEnergyEvent(): void { 129 systemList = []; 130 anomalyList = []; 131 powerList = []; 132} 133 134export function energySysEventReceiver(data: unknown, proc: Function): void { 135 // @ts-ignore 136 if (data.params.trafic === TraficEnum.Memory) { 137 if (systemList.length === 0) { 138 // @ts-ignore 139 systemList = proc(systemDataMemSql(data.params)); 140 } 141 // @ts-ignore 142 systemBufferHandler(data, systemList, data.params.trafic !== TraficEnum.SharedArrayBuffer); 143 // @ts-ignore 144 } else if (data.params.trafic === TraficEnum.ProtoBuffer) { 145 // @ts-ignore 146 let sql = systemDataSql(data.params); 147 let res = proc(sql); 148 // @ts-ignore 149 systemBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer); 150 } 151} 152 153export function hiSysEnergyAnomalyDataReceiver(data: unknown, proc: Function): void { 154 // @ts-ignore 155 if (data.params.trafic === TraficEnum.Memory) { 156 if (anomalyList.length === 0) { 157 // @ts-ignore 158 anomalyList = proc(chartEnergyAnomalyDataSql(data.params)); 159 } 160 // @ts-ignore 161 anomalyBufferHandler(data, anomalyList, data.params.trafic !== TraficEnum.SharedArrayBuffer); 162 // @ts-ignore 163 } else if (data.params.trafic === TraficEnum.ProtoBuffer) { 164 // @ts-ignore 165 let sql = chartEnergyAnomalyDataSql(data.params); 166 let res = proc(sql); 167 // @ts-ignore 168 anomalyBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer); 169 } 170} 171 172export function hiSysEnergyPowerReceiver(data: unknown, proc: Function): void { 173 // @ts-ignore 174 if (data.params.trafic === TraficEnum.Memory) { 175 if (powerList.length === 0) { 176 // @ts-ignore 177 powerList = proc(queryPowerValueSql(data.params)); 178 } 179 // @ts-ignore 180 powerBufferHandler(data, powerList, data.params.trafic !== TraficEnum.SharedArrayBuffer); 181 // @ts-ignore 182 } else if (data.params.trafic === TraficEnum.ProtoBuffer) { 183 // @ts-ignore 184 let sql = queryPowerValueSql(data.params); 185 let res = proc(sql); 186 // @ts-ignore 187 powerBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer); 188 } 189} 190 191export function hiSysEnergyStateReceiver(data: unknown, proc: Function): void { 192 // @ts-ignore 193 if (data.params.trafic === TraficEnum.Memory) { 194 let res: unknown[]; 195 let list: unknown[]; 196 // @ts-ignore 197 if (!energyList.has(data.params.eventName)) { 198 // @ts-ignore 199 list = proc(queryStateDataSql(data.params)); 200 // @ts-ignore 201 energyList.set(data.params.eventName, list); 202 } else { 203 // @ts-ignore 204 list = energyList.get(data.params.eventName) || []; 205 } 206 res = list; 207 // @ts-ignore 208 stateBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer); 209 // @ts-ignore 210 } else if (data.params.trafic === TraficEnum.ProtoBuffer) { 211 // @ts-ignore 212 let stateDataSql = queryStateDataSql(data.params); 213 let stateDataRes = proc(stateDataSql); 214 // @ts-ignore 215 stateBufferHandler(data, stateDataRes, data.params.trafic !== TraficEnum.SharedArrayBuffer); 216 } 217} 218 219function systemBufferHandler(data: unknown, res: unknown[], transfer: boolean): void { 220 let hiSysEnergy = new HiSysEnergy(data, res, transfer); 221 let systemDataList: unknown = []; 222 let workCountMap: Map<string, number> = new Map<string, number>(); 223 let nameIdMap: Map<string, Array<unknown>> = new Map<string, []>(); 224 res.forEach((it, index) => { 225 // @ts-ignore 226 data.params.trafic === TraficEnum.ProtoBuffer && (it = it.energyData); 227 // @ts-ignore 228 let parsedData = it.eventValue; 229 // @ts-ignore 230 if (typeof it.eventValue === 'string') { 231 try { 232 // @ts-ignore 233 parsedData = JSON.parse(it.eventValue); 234 } catch (error) { } 235 } 236 // @ts-ignore 237 it.eventValue = parsedData; 238 let beanData: unknown = {}; 239 // @ts-ignore 240 if (it.appKey === '1') { 241 // @ts-ignore 242 eventNameWithPowerRunninglock(beanData, it, systemDataList); 243 // @ts-ignore 244 } else if (it.appKey === '2') { 245 // @ts-ignore 246 eventNameWithGnssState(beanData, it, systemDataList); 247 } else { 248 // @ts-ignore 249 beanData.dataType = 3; 250 // @ts-ignore 251 if (it.eventValue.NAME) { 252 // @ts-ignore 253 beanData.appName = it.NAME; 254 } 255 // @ts-ignore 256 if (it.eventValue.WORKID) { 257 // @ts-ignore 258 beanData.workId = it.WORKID; 259 } 260 // @ts-ignore 261 if (it.eventName === 'WORK_START') { 262 // @ts-ignore 263 eventNameWithWorkStart(nameIdMap, beanData, workCountMap, it, systemDataList); 264 // @ts-ignore 265 } else if (it.eventName === 'WORK_STOP') { 266 // @ts-ignore 267 eventNameWithWorkStop(nameIdMap, beanData, workCountMap, it, systemDataList); 268 } 269 } 270 // @ts-ignore 271 hiSysEnergy.id[index] = beanData.id; 272 // @ts-ignore 273 hiSysEnergy.startNs[index] = beanData.startNs; 274 // @ts-ignore 275 hiSysEnergy.count[index] = beanData.count; 276 // @ts-ignore 277 hiSysEnergy.type[index] = beanData.dataType; 278 // @ts-ignore 279 hiSysEnergy.token[index] = beanData.token; 280 // @ts-ignore 281 hiSysEnergy.dataType[index] = beanData.dataType; 282 }); 283 postMessage(data, transfer, hiSysEnergy, res.length); 284} 285 286function eventNameWithPowerRunninglock(beanData: unknown, it: unknown, systemDataList: Array<unknown>): void { 287 let lockCount = 0; 288 let tokedIds: Array<string> = []; 289 // @ts-ignore 290 beanData.dataType = 1; 291 // @ts-ignore 292 if (it.eventValue.TAG.endsWith('_ADD')) { 293 // @ts-ignore 294 beanData.startNs = it.startNs; 295 lockCount++; 296 // @ts-ignore 297 beanData.id = it.id; 298 // @ts-ignore 299 beanData.count = lockCount; 300 // @ts-ignore 301 beanData.token = it.eventValue.MESSAGE.split('=')[1]; 302 // @ts-ignore 303 beanData.type = 1; 304 // @ts-ignore 305 tokedIds.push(beanData.token); 306 systemDataList.push(beanData); 307 } else { 308 // @ts-ignore 309 beanData.id = it.id; 310 // @ts-ignore 311 beanData.startNs = it.startNs; 312 // @ts-ignore 313 let toked = it.eventValue.MESSAGE.split('=')[1]; 314 let number = tokedIds.indexOf(toked); 315 if (number > -1) { 316 lockCount--; 317 // @ts-ignore 318 beanData.count = lockCount; 319 // @ts-ignore 320 beanData.token = it.eventValue.MESSAGE.split('=')[1]; 321 // @ts-ignore 322 beanData.type = 1; 323 systemDataList.push(beanData); 324 Reflect.deleteProperty(tokedIds, 'number'); 325 } 326 } 327} 328 329function eventNameWithGnssState(beanData: unknown, it: unknown, systemDataList: Array<unknown>): void { 330 let locationIndex = -1; 331 let locationCount = 0; 332 // @ts-ignore 333 beanData.dataType = 2; 334 // @ts-ignore 335 if (it.eventValue.STATE === 'stop') { 336 if (locationIndex === -1) { 337 // @ts-ignore 338 beanData.startNs = 0; 339 // @ts-ignore 340 beanData.count = 1; 341 } else { 342 // @ts-ignore 343 beanData.startNs = it.startNs; 344 locationCount--; 345 // @ts-ignore 346 beanData.count = locationCount; 347 } 348 // @ts-ignore 349 beanData.state = 'stop'; 350 } else { 351 // @ts-ignore 352 beanData.startNs = it.startNs; 353 locationCount++; 354 // @ts-ignore 355 beanData.count = locationCount; 356 // @ts-ignore 357 beanData.state = 'start'; 358 } 359 locationIndex = 0; 360 // @ts-ignore 361 beanData.type = 2; 362 systemDataList.push(beanData); 363} 364 365function eventNameWithWorkStart( 366 nameIdMap: Map<string, Array<unknown>>, 367 beanData: unknown, 368 workCountMap: Map<string, number>, 369 it: unknown, 370 systemDataList: Array<unknown> 371): void { 372 // @ts-ignore 373 let nameIdList = nameIdMap.get(beanData.appName); 374 let workCount = 0; 375 if (nameIdList === undefined) { 376 workCount = 1; 377 // @ts-ignore 378 nameIdMap.set(beanData.appName, [beanData.workId]); 379 } else { 380 // @ts-ignore 381 nameIdList.push(beanData.workId); 382 workCount = nameIdList.length; 383 } 384 // @ts-ignore 385 let count = workCountMap.get(beanData.appName); 386 if (count === undefined) { 387 // @ts-ignore 388 workCountMap.set(beanData.appName, 1); 389 } else { 390 // @ts-ignore 391 workCountMap.set(beanData.appName, count + 1); 392 } 393 // @ts-ignore 394 beanData.startNs = it.startNs; 395 // @ts-ignore 396 beanData.count = workCount; 397 // @ts-ignore 398 beanData.type = 0; 399 systemDataList.push(beanData); 400} 401 402function eventNameWithWorkStop( 403 nameIdMap: Map<string, Array<unknown>>, 404 beanData: unknown, 405 workCountMap: Map<string, number>, 406 it: unknown, 407 systemDataList: Array<unknown> 408): void { 409 // @ts-ignore 410 let nameIdList: unknown = nameIdMap.get(beanData.appName); 411 // @ts-ignore 412 let index = nameIdList.indexOf(beanData.workId); 413 if (nameIdList !== undefined && index > -1) { 414 // @ts-ignore 415 nameIdList.remove(index); 416 // @ts-ignore 417 let workCount = workCountMap.get(beanData.appName); 418 if (workCount !== undefined) { 419 workCount = workCount - 1; 420 // @ts-ignore 421 workCountMap.set(beanData.appName, workCount); 422 // @ts-ignore 423 beanData.startNs = it.startNs; 424 // @ts-ignore 425 beanData.count = workCount; 426 // @ts-ignore 427 beanData.type = 0; 428 systemDataList.push(beanData); 429 } 430 } 431} 432 433function postMessage(data: unknown, transfer: boolean, hiSysEnergy: HiSysEnergy, len: number): void { 434 (self as unknown as Worker).postMessage( 435 { 436 // @ts-ignore 437 id: data.id, 438 // @ts-ignore 439 action: data.action, 440 results: transfer 441 ? { 442 id: hiSysEnergy.id.buffer, 443 startNs: hiSysEnergy.startNs.buffer, 444 count: hiSysEnergy.count.buffer, 445 type: hiSysEnergy.type.buffer, 446 token: hiSysEnergy.token.buffer, 447 dataType: hiSysEnergy.dataType.buffer, 448 } 449 : {}, 450 len: len, 451 transfer: transfer, 452 }, 453 transfer 454 ? [ 455 hiSysEnergy.id.buffer, 456 hiSysEnergy.startNs.buffer, 457 hiSysEnergy.count.buffer, 458 hiSysEnergy.type.buffer, 459 hiSysEnergy.token.buffer, 460 hiSysEnergy.dataType.buffer, 461 ] 462 : [] 463 ); 464} 465 466class HiSysEnergy { 467 id: Uint16Array; 468 startNs: Float64Array; 469 count: Uint32Array; 470 type: Uint32Array; 471 token: Float64Array; 472 dataType: Uint16Array; 473 474 constructor(data: unknown, res: unknown[], transfer: boolean) { 475 // @ts-ignore 476 this.id = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.id); 477 // @ts-ignore 478 this.startNs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startNs); 479 // @ts-ignore 480 this.count = new Uint32Array(transfer ? res.length : data.params.sharedArrayBuffers.count); 481 // @ts-ignore 482 this.type = new Uint32Array(transfer ? res.length : data.params.sharedArrayBuffers.type); 483 // @ts-ignore 484 this.token = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.token); 485 // @ts-ignore 486 this.dataType = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.dataType); 487 } 488} 489 490function anomalyBufferHandler(data: unknown, res: unknown[], transfer: boolean): void { 491 // @ts-ignore 492 let id = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.id); 493 // @ts-ignore 494 let startNs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startNs); 495 res.forEach((it, index) => { 496 // @ts-ignore 497 data.params.trafic === TraficEnum.ProtoBuffer && (it = it.energyData); 498 // @ts-ignore 499 id[index] = it.id; 500 // @ts-ignore 501 startNs[index] = it.startNs; 502 }); 503 (self as unknown as Worker).postMessage( 504 { 505 // @ts-ignore 506 id: data.id, 507 // @ts-ignore 508 action: data.action, 509 results: transfer 510 ? { 511 id: id.buffer, 512 startNs: startNs.buffer, 513 } 514 : {}, 515 len: res.length, 516 transfer: transfer, 517 }, 518 transfer ? [startNs.buffer, id.buffer] : [] 519 ); 520} 521 522function powerBufferHandler(data: unknown, res: unknown[], transfer: boolean): void { 523 // @ts-ignore 524 let id = new Uint32Array(transfer ? res.length : data.params.sharedArrayBuffers.id); 525 // @ts-ignore 526 let startNs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startNs); 527 res.forEach((it, index) => { 528 // @ts-ignore 529 data.params.trafic === TraficEnum.ProtoBuffer && (it = it.energyData); 530 // @ts-ignore 531 id[index] = it.id; 532 // @ts-ignore 533 startNs[index] = it.startNs; 534 }); 535 (self as unknown as Worker).postMessage( 536 { 537 // @ts-ignore 538 id: data.id, 539 // @ts-ignore 540 action: data.action, 541 results: transfer 542 ? { 543 id: id.buffer, 544 startNs: startNs.buffer, 545 } 546 : {}, 547 len: res.length, 548 transfer: transfer, 549 }, 550 transfer ? [id.buffer, startNs.buffer] : [] 551 ); 552} 553 554function stateBufferHandler(data: unknown, res: unknown[], transfer: boolean): void { 555 // @ts-ignore 556 let startNs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startNs); 557 // @ts-ignore 558 let eventValue = new Float32Array(transfer ? res.length : data.params.sharedArrayBuffers.eventValue); 559 // @ts-ignore 560 let id = new Uint32Array(transfer ? res.length : data.params.sharedArrayBuffers.id); 561 res.forEach((it, index) => { 562 // @ts-ignore 563 data.params.trafic === TraficEnum.ProtoBuffer && (it = it.energyData); 564 // @ts-ignore 565 id[index] = it.id; 566 // @ts-ignore 567 startNs[index] = it.startNs; 568 // @ts-ignore 569 let eventName = it.eventName.toLocaleLowerCase(); 570 if (eventName.includes('sensor')) { 571 if (eventName.includes('enable')) { 572 eventValue[index] = 0; 573 } else { 574 eventValue[index] = 1; 575 } 576 } else { 577 // @ts-ignore 578 eventValue[index] = it.eventValue; 579 } 580 }); 581 (self as unknown as Worker).postMessage( 582 { 583 // @ts-ignore 584 id: data.id, 585 // @ts-ignore 586 action: data.action, 587 results: transfer 588 ? { 589 id: id.buffer, 590 startNs: startNs.buffer, 591 eventValue: eventValue.buffer, 592 } 593 : {}, 594 len: res.length, 595 transfer: transfer, 596 }, 597 transfer ? [id.buffer, startNs.buffer, eventValue.buffer] : [] 598 ); 599} 600