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