1/* 2 * Copyright (c) 2021-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 16#include "cpu_time_reader.h" 17 18#include <fstream> 19#include "string_ex.h" 20 21#include "battery_stats_service.h" 22#include "stats_helper.h" 23#include "stats_log.h" 24#include "stats_utils.h" 25 26namespace OHOS { 27namespace PowerMgr { 28namespace { 29static const std::string UID_CPU_ACTIVE_TIME_FILE = "/proc/uid_concurrent_active_time"; 30static const std::string UID_CPU_CLUSTER_TIME_FILE = "/proc/uid_concurrent_policy_time"; 31static const std::string UID_CPU_FREQ_TIME_FILE = "/proc/uid_time_in_state"; 32static const std::string UID_CPU_TIME_FILE = "/proc/uid_cputime/show_uid_stat"; 33} // namespace 34bool CpuTimeReader::Init() 35{ 36 if (!UpdateCpuTime()) { 37 STATS_HILOGW(COMP_SVC, "Update cpu time failed"); 38 } 39 return true; 40} 41 42int64_t CpuTimeReader::GetUidCpuActiveTimeMs(int32_t uid) 43{ 44 int64_t cpuActiveTime = 0; 45 auto iter = activeTimeMap_.find(uid); 46 if (iter != activeTimeMap_.end()) { 47 cpuActiveTime = iter->second; 48 STATS_HILOGD(COMP_SVC, "Get cpu active time: %{public}s for uid: %{public}d", 49 std::to_string(cpuActiveTime).c_str(), uid); 50 } else { 51 STATS_HILOGD(COMP_SVC, "No cpu active time found for uid: %{public}d, return 0", uid); 52 } 53 return cpuActiveTime; 54} 55 56void CpuTimeReader::DumpInfo(std::string& result, int32_t uid) 57{ 58 auto uidIter = lastUidTimeMap_.find(uid); 59 if (uidIter == lastUidTimeMap_.end()) { 60 STATS_HILOGE(COMP_SVC, "No related CPU info for uid: %{public}d", uid); 61 return; 62 } 63 std::string freqTime = ""; 64 auto freqIter = lastFreqTimeMap_.find(uid); 65 if (freqIter != lastFreqTimeMap_.end()) { 66 for (auto timeIter = freqIter->second.begin(); timeIter != freqIter->second.end(); timeIter++) { 67 for (uint32_t i = 0; i < timeIter->second.size(); i++) { 68 freqTime.append(ToString(timeIter->second[i])) 69 .append(" "); 70 } 71 } 72 } 73 result.append("Total cpu time: userSpaceTime=") 74 .append(ToString(uidIter->second[0])) 75 .append("ms, systemSpaceTime=") 76 .append(ToString(uidIter->second[1])) 77 .append("ms\n") 78 .append("Total cpu time per freq: ") 79 .append(freqTime) 80 .append("\n"); 81} 82 83int64_t CpuTimeReader::GetUidCpuClusterTimeMs(int32_t uid, uint32_t cluster) 84{ 85 int64_t cpuClusterTime = 0; 86 auto iter = clusterTimeMap_.find(uid); 87 if (iter != clusterTimeMap_.end()) { 88 auto cpuClusterTimeVector = iter->second; 89 if (cluster < cpuClusterTimeVector.size()) { 90 cpuClusterTime = cpuClusterTimeVector[cluster]; 91 STATS_HILOGD(COMP_SVC, "Get cpu cluster time: %{public}s of cluster: %{public}d", 92 std::to_string(cpuClusterTime).c_str(), cluster); 93 } else { 94 STATS_HILOGD(COMP_SVC, "No cpu cluster time of cluster: %{public}d found, return 0", cluster); 95 } 96 } else { 97 STATS_HILOGD(COMP_SVC, "No cpu cluster time vector found for uid: %{public}d, return 0", uid); 98 } 99 return cpuClusterTime; 100} 101 102int64_t CpuTimeReader::GetUidCpuFreqTimeMs(int32_t uid, uint32_t cluster, uint32_t speed) 103{ 104 int64_t cpuFreqTime = 0; 105 auto uidIter = freqTimeMap_.find(uid); 106 if (uidIter != freqTimeMap_.end()) { 107 auto cpuFreqTimeMap = uidIter->second; 108 auto clusterIter = cpuFreqTimeMap.find(cluster); 109 if (clusterIter != cpuFreqTimeMap.end()) { 110 auto cpuFreqTimeVector = clusterIter->second; 111 if (speed < cpuFreqTimeVector.size()) { 112 cpuFreqTime = cpuFreqTimeVector[speed]; 113 STATS_HILOGD(COMP_SVC, "Get cpu freq time: %{public}s of speed: %{public}d", 114 std::to_string(cpuFreqTime).c_str(), speed); 115 } else { 116 STATS_HILOGD(COMP_SVC, "No cpu freq time of speed: %{public}d found, return 0", speed); 117 } 118 } else { 119 STATS_HILOGD(COMP_SVC, "No cluster cpu freq time vector of cluster: %{public}d found, return 0", 120 cluster); 121 } 122 } else { 123 STATS_HILOGD(COMP_SVC, "No uid cpu freq time map found for uid: %{public}d, return 0", uid); 124 } 125 return cpuFreqTime; 126} 127 128std::vector<int64_t> CpuTimeReader::GetUidCpuTimeMs(int32_t uid) 129{ 130 std::vector<int64_t> cpuTimeVec; 131 auto iter = uidTimeMap_.find(uid); 132 if (iter != uidTimeMap_.end()) { 133 cpuTimeVec = iter->second; 134 STATS_HILOGD(COMP_SVC, "Get uid cpu time vector for uid: %{public}d, size: %{public}d", uid, 135 static_cast<int32_t>(cpuTimeVec.size())); 136 } else { 137 STATS_HILOGD(COMP_SVC, "No uid cpu time vector found for uid: %{public}d, return null", uid); 138 } 139 return cpuTimeVec; 140} 141 142bool CpuTimeReader::UpdateCpuTime() 143{ 144 bool result = true; 145 if (!ReadUidCpuClusterTime()) { 146 STATS_HILOGW(COMP_SVC, "Read uid cpu cluster time failed"); 147 result = false; 148 } 149 150 if (!ReadUidCpuTime()) { 151 STATS_HILOGW(COMP_SVC, "Read uid cpu time failed"); 152 result = false; 153 } 154 155 if (!ReadUidCpuActiveTime()) { 156 STATS_HILOGW(COMP_SVC, "Read uid cpu active time failed"); 157 result = false; 158 } 159 160 if (!ReadUidCpuFreqTime()) { 161 STATS_HILOGW(COMP_SVC, "Read uid cpu freq time failed"); 162 result = false; 163 } 164 return result; 165} 166 167bool CpuTimeReader::ReadUidCpuActiveTimeImpl(std::string& line, int32_t uid) 168{ 169 int64_t timeMs = 0; 170 std::vector<std::string> splitedTime; 171 Split(line, ' ', splitedTime); 172 for (uint16_t i = 0; i < splitedTime.size(); i++) { 173 timeMs += stoll(splitedTime[i]) * 10; // Unit is 10ms 174 } 175 176 int64_t increment = 0; 177 if (timeMs > 0) { 178 auto iterLast = lastActiveTimeMap_.find(uid); 179 if (iterLast != lastActiveTimeMap_.end()) { 180 increment = timeMs - iterLast->second; 181 if (increment >= 0) { 182 iterLast->second = timeMs; 183 } else { 184 STATS_HILOGI(COMP_SVC, "Negative cpu active time increment"); 185 return false; 186 } 187 } else { 188 lastActiveTimeMap_.insert(std::pair<int32_t, int64_t>(uid, timeMs)); 189 increment = timeMs; 190 } 191 } 192 193 if (StatsHelper::IsOnBattery()) { 194 STATS_HILOGD(COMP_SVC, "Power supply is not connected. Add the increment"); 195 auto iter = activeTimeMap_.find(uid); 196 if (iter != activeTimeMap_.end()) { 197 iter->second += increment; 198 } else { 199 activeTimeMap_.insert(std::pair<int32_t, int64_t>(uid, increment)); 200 STATS_HILOGI(COMP_SVC, "Add active time: %{public}sms, uid: %{public}d", 201 std::to_string(increment).c_str(), uid); 202 } 203 } 204 return true; 205} 206 207bool CpuTimeReader::ReadUidCpuActiveTime() 208{ 209 std::ifstream input(UID_CPU_ACTIVE_TIME_FILE); 210 if (!input) { 211 STATS_HILOGW(COMP_SVC, "Open file failed"); 212 return false; 213 } 214 215 std::string line; 216 const int32_t INDEX_0 = 0; 217 const int32_t INDEX_1 = 1; 218 while (getline(input, line)) { 219 int32_t uid = StatsUtils::INVALID_VALUE; 220 std::vector<std::string> splitedLine; 221 Split(line, ':', splitedLine); 222 if (splitedLine[INDEX_0] == "cpus") { 223 continue; 224 } else { 225 uid = stoi(splitedLine[INDEX_0]); 226 } 227 228 if (uid > StatsUtils::INVALID_VALUE) { 229 auto bss = BatteryStatsService::GetInstance(); 230 auto uidEntity = 231 bss->GetBatteryStatsCore()->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_APP); 232 if (uidEntity) { 233 uidEntity->UpdateUidMap(uid); 234 } 235 } 236 237 if (ReadUidCpuActiveTimeImpl(splitedLine[INDEX_1], uid)) { 238 continue; 239 } else { 240 return false; 241 } 242 } 243 return true; 244} 245 246void CpuTimeReader::ReadPolicy(std::vector<uint16_t>& clusters, std::string& line) 247{ 248 std::vector<std::string> splitedPolicy; 249 Split(line, ' ', splitedPolicy); 250 uint32_t step = 2; 251 for (uint32_t i = 0; i < splitedPolicy.size(); i += step) { 252 uint16_t coreNum = static_cast<uint16_t>(stoi(splitedPolicy[i + 1])); 253 clusters.push_back(coreNum); 254 clustersMap_.insert(std::pair<uint16_t, uint16_t>(i, coreNum)); 255 } 256} 257 258bool CpuTimeReader::ReadClusterTimeIncrement(std::vector<int64_t>& clusterTime, std::vector<int64_t>& increments, 259 int32_t uid, std::vector<uint16_t>& clusters, std::string& timeLine) 260{ 261 std::vector<std::string> splitedTime; 262 Split(timeLine, ' ', splitedTime); 263 uint16_t count = 0; 264 for (uint16_t i = 0; i < clusters.size(); i++) { 265 int64_t tempTimeMs = 0; 266 for (uint16_t j = 0; j < clusters[i]; j++) { 267 tempTimeMs += stoll(splitedTime[count++]) * 10; // Unit is 10ms 268 } 269 clusterTime.push_back(tempTimeMs); 270 } 271 272 auto iterLast = lastClusterTimeMap_.find(uid); 273 if (iterLast != lastClusterTimeMap_.end()) { 274 for (uint16_t i = 0; i < clusters.size(); i++) { 275 int64_t increment = clusterTime[i] - iterLast->second[i]; 276 if (increment >= 0) { 277 iterLast->second[i] = clusterTime[i]; 278 increments.push_back(increment); 279 } else { 280 STATS_HILOGD(COMP_SVC, "Negative cpu cluster time increment"); 281 return false; 282 } 283 } 284 } else { 285 lastClusterTimeMap_.insert(std::pair<int32_t, std::vector<int64_t>>(uid, clusterTime)); 286 increments = clusterTime; 287 STATS_HILOGI(COMP_SVC, "Add last cpu cluster time for uid: %{public}d", uid); 288 } 289 return true; 290} 291 292bool CpuTimeReader::ReadUidCpuClusterTime() 293{ 294 std::ifstream input(UID_CPU_CLUSTER_TIME_FILE); 295 if (!input) { 296 STATS_HILOGW(COMP_SVC, "Open file failed"); 297 return false; 298 } 299 std::string line; 300 int32_t uid = -1; 301 std::vector<uint16_t> clusters; 302 std::vector<int64_t> clusterTime; 303 while (getline(input, line)) { 304 clusterTime.clear(); 305 if (line.find("policy") != line.npos) { 306 ReadPolicy(clusters, line); 307 continue; 308 } 309 310 std::vector<std::string> splitedLine; 311 Split(line, ':', splitedLine); 312 uid = stoi(splitedLine[0]); 313 if (uid > StatsUtils::INVALID_VALUE) { 314 auto bss = BatteryStatsService::GetInstance(); 315 auto uidEntity = bss->GetBatteryStatsCore()->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_APP); 316 if (uidEntity) { 317 uidEntity->UpdateUidMap(uid); 318 } 319 } 320 321 std::vector<int64_t> increments; 322 if (!ReadClusterTimeIncrement(clusterTime, increments, uid, clusters, splitedLine[1])) { 323 return false; 324 } 325 326 if (StatsHelper::IsOnBattery()) { 327 STATS_HILOGD(COMP_SVC, "Power supply is not connected. Add the increment"); 328 auto iter = clusterTimeMap_.find(uid); 329 if (iter != clusterTimeMap_.end()) { 330 AddIncrementsToClusterTime(iter->second, increments, clusters); 331 } else { 332 clusterTimeMap_.insert(std::pair<int32_t, std::vector<int64_t>>(uid, increments)); 333 STATS_HILOGI(COMP_SVC, "Add cpu cluster time for uid: %{public}d", uid); 334 } 335 } 336 } 337 return true; 338} 339 340void CpuTimeReader::AddIncrementsToClusterTime(std::vector<int64_t>& clusterTime, 341 const std::vector<int64_t>& increments, const std::vector<uint16_t>& clusters) 342{ 343 for (uint16_t i = 0; i < clusters.size(); i++) { 344 clusterTime[i] += increments[i]; 345 } 346} 347 348bool CpuTimeReader::ProcessFreqTime(std::map<uint32_t, std::vector<int64_t>>& map, std::map<uint32_t, 349 std::vector<int64_t>>& increments, std::map<uint32_t, std::vector<int64_t>>& speedTime, int32_t index, int32_t uid) 350{ 351 auto iterLastTemp = map.find(index); 352 if (iterLastTemp != map.end()) { 353 std::vector<int64_t> lastSpeedTimes = iterLastTemp->second; 354 std::vector<int64_t> newIncrementTimes; 355 newIncrementTimes.clear(); 356 for (uint16_t j = 0; j < lastSpeedTimes.size(); j++) { 357 int64_t increment = speedTime.at(index)[j] - lastSpeedTimes[j]; 358 if (increment >= 0) { 359 newIncrementTimes.push_back(increment); 360 increments.insert(std::pair<uint32_t, std::vector<int64_t>>(index, newIncrementTimes)); 361 } else { 362 STATS_HILOGI(COMP_SVC, "Negative cpu freq time increment"); 363 return false; 364 } 365 } 366 iterLastTemp->second = speedTime.at(index); 367 } 368 return true; 369} 370 371bool CpuTimeReader::ReadFreqTimeIncrement(std::map<uint32_t, std::vector<int64_t>>& speedTime, 372 std::map<uint32_t, std::vector<int64_t>>& increments, int32_t uid, std::vector<std::string>& splitedTime) 373{ 374 auto bss = BatteryStatsService::GetInstance(); 375 auto parser = bss->GetBatteryStatsParser(); 376 uint16_t clusterNum = parser->GetClusterNum(); 377 uint16_t count = 0; 378 for (uint16_t i = 0; i < clusterNum; i++) { 379 std::vector<int64_t> tempSpeedTimes; 380 tempSpeedTimes.clear(); 381 for (uint16_t j = 0; j < parser->GetSpeedNum(i); j++) { 382 int64_t tempTimeMs = stoll(splitedTime[count++]) * 10; // Unit is 10ms 383 tempSpeedTimes.push_back(tempTimeMs); 384 } 385 speedTime.insert(std::pair<uint32_t, std::vector<int64_t>>(i, tempSpeedTimes)); 386 } 387 388 auto iterLast = lastFreqTimeMap_.find(uid); 389 if (iterLast == lastFreqTimeMap_.end()) { 390 lastFreqTimeMap_.insert(std::pair<int32_t, std::map<uint32_t, std::vector<int64_t>>>(uid, speedTime)); 391 increments = speedTime; 392 STATS_HILOGI(COMP_SVC, "Add last cpu freq time for uid: %{public}d", uid); 393 return true; 394 } 395 for (uint16_t i = 0; i < lastFreqTimeMap_.size(); i++) { 396 if (!ProcessFreqTime(iterLast->second, increments, speedTime, i, uid)) { 397 return false; 398 } 399 } 400 return true; 401} 402 403void CpuTimeReader::DistributeFreqTime(std::map<uint32_t, std::vector<int64_t>>& uidIncrements, 404 std::map<uint32_t, std::vector<int64_t>>& increments) 405{ 406 auto bss = BatteryStatsService::GetInstance(); 407 auto parser = bss->GetBatteryStatsParser(); 408 uint16_t clusterNum = parser->GetClusterNum(); 409 if (wakelockCounts_ > 0) { 410 for (uint16_t i = 0; i < clusterNum; i++) { 411 uint16_t speedNum = parser->GetSpeedNum(i); 412 for (uint16_t j = 0; j < speedNum; j++) { 413 int32_t step = 2; 414 uidIncrements.at(i)[j] = increments.at(i)[j] / step; 415 } 416 } 417 // TO-DO, distribute half of cpu freq time to wakelock holders 418 } 419} 420 421void CpuTimeReader::AddFreqTimeToUid(std::map<uint32_t, std::vector<int64_t>>& uidIncrements, int32_t uid) 422{ 423 auto bss = BatteryStatsService::GetInstance(); 424 auto parser = bss->GetBatteryStatsParser(); 425 uint16_t clusterNum = parser->GetClusterNum(); 426 auto iter = freqTimeMap_.find(uid); 427 if (iter != freqTimeMap_.end()) { 428 for (uint16_t i = 0; i < clusterNum; i++) { 429 uint16_t speedNum = parser->GetSpeedNum(i); 430 for (uint16_t j = 0; j < speedNum; j++) { 431 iter->second.at(i)[j] += uidIncrements.at(i)[j]; 432 } 433 } 434 } else { 435 freqTimeMap_.insert(std::pair<int32_t, std::map<uint32_t, std::vector<int64_t>>>(uid, uidIncrements)); 436 STATS_HILOGI(COMP_SVC, "Add cpu freq time for uid: %{public}d", uid); 437 } 438} 439 440bool CpuTimeReader::ReadUidCpuFreqTime() 441{ 442 std::ifstream input(UID_CPU_FREQ_TIME_FILE); 443 if (!input) { 444 STATS_HILOGW(COMP_SVC, "Open file failed"); 445 return false; 446 } 447 std::string line; 448 int32_t uid = -1; 449 std::map<uint32_t, std::vector<int64_t>> speedTime; 450 while (getline(input, line)) { 451 speedTime.clear(); 452 std::vector<std::string> splitedLine; 453 Split(line, ':', splitedLine); 454 if (splitedLine[0] == "uid") { 455 continue; 456 } else { 457 uid = stoi(splitedLine[0]); 458 } 459 460 if (uid > StatsUtils::INVALID_VALUE) { 461 auto bss = BatteryStatsService::GetInstance(); 462 auto uidEntity = 463 bss->GetBatteryStatsCore()->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_APP); 464 if (uidEntity) { 465 uidEntity->UpdateUidMap(uid); 466 } 467 } 468 469 std::vector<std::string> splitedTime; 470 Split(splitedLine[1], ' ', splitedTime); 471 472 std::map<uint32_t, std::vector<int64_t>> increments; 473 if (!ReadFreqTimeIncrement(speedTime, increments, uid, splitedTime)) { 474 return false; 475 } 476 477 std::map<uint32_t, std::vector<int64_t>> uidIncrements = increments; 478 DistributeFreqTime(uidIncrements, increments); 479 480 if (!StatsHelper::IsOnBattery()) { 481 STATS_HILOGD(COMP_SVC, "Power supply is connected, don't add the increment"); 482 continue; 483 } 484 AddFreqTimeToUid(uidIncrements, uid); 485 } 486 return true; 487} 488 489bool CpuTimeReader::ReadUidTimeIncrement(std::vector<int64_t>& cpuTime, std::vector<int64_t>& uidIncrements, 490 int32_t uid, std::string& timeLine) 491{ 492 std::vector<std::string> splitedTime; 493 Split(timeLine, ' ', splitedTime); 494 for (uint16_t i = 0; i < splitedTime.size(); i++) { 495 int64_t tempTime = 0; 496 tempTime = stoll(splitedTime[i]); 497 cpuTime.push_back(tempTime); 498 } 499 500 std::vector<int64_t> increments; 501 auto iterLast = lastUidTimeMap_.find(uid); 502 if (iterLast != lastUidTimeMap_.end()) { 503 for (uint16_t i = 0; i < splitedTime.size(); i++) { 504 int64_t increment = 0; 505 increment = cpuTime[i] - iterLast->second[i]; 506 if (increment >= 0) { 507 iterLast->second[i] = cpuTime[i]; 508 increments.push_back(increment); 509 } else { 510 STATS_HILOGI(COMP_SVC, "Negative cpu time increment"); 511 return false; 512 } 513 } 514 } else { 515 lastUidTimeMap_.insert(std::pair<int32_t, std::vector<int64_t>>(uid, cpuTime)); 516 increments = cpuTime; 517 STATS_HILOGI(COMP_SVC, "Add last cpu time for uid: %{public}d", uid); 518 } 519 520 uidIncrements = increments; 521 522 if (wakelockCounts_ > 0) { 523 double weight = 0.5; 524 uidIncrements[0] = increments[0] / (StatsUtils::US_IN_MS * 1.0) * weight; 525 uidIncrements[1] = increments[1] / (StatsUtils::US_IN_MS * 1.0) * weight; 526 // TO-DO, distribute half of cpu time to wakelock holders 527 } 528 return true; 529} 530 531bool CpuTimeReader::ReadUidCpuTime() 532{ 533 std::ifstream input(UID_CPU_TIME_FILE); 534 if (!input) { 535 STATS_HILOGW(COMP_SVC, "Open file failed"); 536 return false; 537 } 538 std::string line; 539 std::vector<int64_t> cpuTime; 540 while (getline(input, line)) { 541 cpuTime.clear(); 542 std::vector<std::string> splitedLine; 543 Split(line, ':', splitedLine); 544 int32_t uid = stoi(splitedLine[0]); 545 if (uid > StatsUtils::INVALID_VALUE) { 546 auto bss = BatteryStatsService::GetInstance(); 547 auto uidEntity = 548 bss->GetBatteryStatsCore()->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_APP); 549 if (uidEntity) { 550 uidEntity->UpdateUidMap(uid); 551 } 552 } 553 554 std::vector<int64_t> uidIncrements; 555 if (!ReadUidTimeIncrement(cpuTime, uidIncrements, uid, splitedLine[1])) { 556 return false; 557 } 558 559 if (StatsHelper::IsOnBattery()) { 560 STATS_HILOGD(COMP_SVC, "Power supply is not connected. Add the increment"); 561 UpdateUidTimeMap(uid, uidIncrements); 562 } 563 } 564 return true; 565} 566 567void CpuTimeReader::UpdateUidTimeMap(int32_t uid, const std::vector<int64_t>& uidIncrements) 568{ 569 auto iter = uidTimeMap_.find(uid); 570 if (iter != uidTimeMap_.end()) { 571 for (uint16_t i = 0; i < uidIncrements.size(); i++) { 572 iter->second[i] = uidIncrements[i]; 573 } 574 } else { 575 uidTimeMap_.insert(std::pair<int32_t, std::vector<int64_t>>(uid, uidIncrements)); 576 STATS_HILOGI(COMP_SVC, "Add cpu time for uid: %{public}d", uid); 577 } 578} 579 580void CpuTimeReader::Split(std::string &origin, char delimiter, std::vector<std::string> &splited) 581{ 582 size_t start; 583 size_t end = 0; 584 585 while ((start = origin.find_first_not_of(delimiter, end)) != std::string::npos) { 586 end = origin.find(delimiter, start); 587 splited.push_back(origin.substr(start, end - start)); 588 } 589} 590} // namespace PowerMgr 591} // namespace OHOS