1/* 2 * Copyright (c) 2021-2024 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 "utilities.h" 17 18#include <zlib.h> 19#include <thread> 20#if defined(CONFIG_HAS_SYSPARA) && defined(is_ohos) && is_ohos 21#include <parameters.h> 22#endif 23#if defined(is_mingw) && is_mingw 24#include <io.h> 25#endif 26 27#include "hiperf_hilog.h" 28#if defined(is_ohos) && is_ohos && defined(BUNDLE_FRAMEWORK_ENABLE) 29#include "application_info.h" 30#include "bundle_mgr_proxy.h" 31#endif 32#if defined(is_ohos) && is_ohos 33#include "iservice_registry.h" 34#include "system_ability_definition.h" 35using namespace OHOS; 36using namespace OHOS::AppExecFwk; 37#endif 38 39using namespace std::chrono; 40namespace OHOS { 41namespace Developtools { 42namespace HiPerf { 43 44static const std::string USER_DOMESTIC_BETA = "beta"; 45static const std::string USER_TYPE_PARAM = "const.logsystem.versiontype"; 46static const std::string USER_TYPE_PARAM_GET = ""; 47static const std::string HIVIEW_CMDLINE = "/system/bin/hiview"; 48 49std::string CanonicalizeSpecPath(const char* src) 50{ 51 if (src == nullptr) { 52 HLOGE("Error: CanonicalizeSpecPath failed"); 53 return ""; 54 } else if (strlen(src) >= PATH_MAX) { 55 HLOGE("Error: CanonicalizeSpecPath %s failed", src); 56 return ""; 57 } 58 char resolvedPath[PATH_MAX] = { 0 }; 59#if defined(_WIN32) 60 if (!_fullpath(resolvedPath, src, PATH_MAX)) { 61 HLOGE("Error: _fullpath %s failed", src); 62 return ""; 63 } 64#else 65 if (access(src, F_OK) == 0) { 66 if (strstr(src, "/proc/") == src && strstr(src, "/data/storage") != nullptr) { // for sandbox 67 if (strncpy_s(resolvedPath, sizeof(resolvedPath), src, strlen(src)) == -1) { 68 HLOGE("Error: strncpy_s %s failed", src); 69 return ""; 70 } 71 } else if (realpath(src, resolvedPath) == nullptr) { 72 HLOGE("Error: realpath %s failed", src); 73 return ""; 74 } 75 } else { 76 std::string fileName(src); 77 if (fileName.find("..") == std::string::npos) { 78 if (sprintf_s(resolvedPath, PATH_MAX, "%s", src) == -1) { 79 HLOGE("Error: sprintf_s %s failed", src); 80 return ""; 81 } 82 } else { 83 HLOGE("Error: find .. %s failed", src); 84 return ""; 85 } 86 } 87#endif 88 std::string res(resolvedPath); 89 return res; 90} 91 92uint32_t RoundUp(uint32_t x, const int align) 93{ 94 return (((x) + (align) >= 1 ? (x) + (align) - 1 : 0) / (align)) * (align); 95} 96 97std::string StringReplace(std::string source, const std::string &from, const std::string &to) 98{ 99 size_t pos = 0; 100 std::string result; 101 // find 102 while ((pos = source.find(from)) != std::string::npos) { 103 // replace 104 result.append(source.substr(0, pos) + to); 105 source.erase(0, pos + from.length()); 106 } 107 // add last token 108 result.append(source); 109 return result; 110} 111 112size_t SubStringCount(const std::string &source, const std::string &sub) 113{ 114 size_t count(0); 115 size_t pos(0); 116 if (sub.empty()) { 117 return source.size(); 118 } 119 while ((pos = source.find(sub, pos)) != std::string::npos) { 120 pos += sub.size(); 121 count++; 122 } 123 return count; 124} 125 126std::vector<std::string> StringSplit(std::string source, const std::string &split) 127{ 128 std::vector<std::string> result; 129 130 // find 131 if (!split.empty()) { 132 size_t pos = 0; 133 while ((pos = source.find(split)) != std::string::npos) { 134 // split 135 std::string token = source.substr(0, pos); 136 if (!token.empty()) { 137 result.push_back(token); 138 } 139 source.erase(0, pos + split.length()); 140 } 141 } 142 // add last token 143 if (!source.empty()) { 144 result.push_back(source); 145 } 146 return result; 147} 148StdoutRecord::StdoutRecord(const std::string &tempFile, const std::string &mode) 149{ 150 if (!tempFile.empty()) { 151 std::string resolvedPath = CanonicalizeSpecPath(tempFile.c_str()); 152 recordFile_ = fopen(resolvedPath.c_str(), mode.c_str()); 153 if (recordFile_ == nullptr) { 154 HLOGE("tmpfile create failed '%s' with mode '%s'", tempFile.c_str(), mode.c_str()); 155 } else { 156 // auto start it 157 Start(); 158 } 159 } 160} 161bool StdoutRecord::Start() 162{ 163 content_ = EMPTY_STRING; 164 fflush(stdout); 165 166 // we will save output here 167 if (recordFile_ == nullptr) { 168 recordFile_ = std::tmpfile(); 169 } 170 if (recordFile_ == nullptr) { 171 // try second way 172 std::string fileName = "/data/local/tmp/temp.stdout"; 173 std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str()); 174 recordFile_ = fopen(resolvedPath.c_str(), "w+"); 175 if (recordFile_ == nullptr) { 176 HLOGF("tmpfile create failed '%s'", fileName.c_str()); 177 return false; 178 } 179 } 180 181 // we save the stdout 182 stdoutFile_ = OHOS::UniqueFd(dup(STDOUT_FILENO)); 183 CHECK_TRUE(stdoutFile_ == -1, false, 1, "std dup failed"); 184 185 // setup temp file as stdout 186 if (dup2(fileno(recordFile_), STDOUT_FILENO) != -1) { 187 stop_ = false; 188 return true; 189 } else { 190 HLOGF("std dup2 failed"); 191 return false; 192 } 193} 194 195std::string StdoutRecord::Stop() 196{ 197 if (stop_) { 198 return content_; 199 } 200 fflush(stdout); 201 // restore fd 202 dup2(stdoutFile_, STDOUT_FILENO); 203 204 // return file content 205 if (recordFile_ != nullptr) { 206 const long fileLength = lseek(fileno(recordFile_), 0, SEEK_END); 207 content_.resize(fileLength); 208 lseek(fileno(recordFile_), 0, SEEK_SET); 209 const long len = read(fileno(recordFile_), content_.data(), fileLength); 210 std::fclose(recordFile_); 211 recordFile_ = nullptr; 212 if (len < 0) { 213 HLOGE("tmp file read failed (try read %ld)", fileLength); 214 } else if (len < fileLength) { 215 HLOGE("not all the data is read, lost %ld/%ld bytes", fileLength - len, fileLength); 216 } 217 } else { 218 HLOGE("recordFile_ is nullptr"); 219 } 220 stop_ = true; 221 return content_; 222} 223 224bool IsDigits(const std::string &str) 225{ 226 if (str.empty()) { 227 return false; 228 } else { 229 return std::all_of(str.begin(), str.end(), ::isdigit); 230 } 231} 232 233bool IsHexDigits(const std::string &str) 234{ 235 if (str.empty()) { 236 return false; 237 } 238 const std::string prefix {"0x"}; 239 std::string effectStr {str}; 240 if (prefix.compare(0, prefix.size(), effectStr.substr(0, prefix.size())) == 0) { 241 effectStr = effectStr.substr(prefix.size(), effectStr.size() - prefix.size()); 242 } 243 CHECK_TRUE(effectStr.empty(), false, 0, ""); 244 std::size_t start {0}; 245 for (; start < effectStr.size(); ++start) { 246 if (effectStr[start] == '0') { 247 continue; 248 } 249 break; 250 } 251 if (start == effectStr.size()) { 252 effectStr = "0"; 253 } 254 return std::all_of(effectStr.begin(), effectStr.end(), ::isxdigit); 255} 256 257bool IsDir(const std::string &path) 258{ 259 struct stat st; 260 if (stat(path.c_str(), &st) == 0) { 261 return S_ISDIR(st.st_mode); 262 } 263 return false; 264} 265 266bool IsPath(const std::string &fileName) 267{ 268 HLOG_ASSERT(!fileName.empty()); 269 if (fileName[0] == PATH_SEPARATOR) { 270 return true; 271 } 272 const int prefixPathLen = 2; 273 if (fileName.substr(0, prefixPathLen) == "./") { 274 return true; 275 } 276 return false; 277} 278 279std::string PlatformPathConvert(const std::string &path) 280{ 281#if defined(is_mingw) && is_mingw 282 return StringReplace(path, "/", "\\"); 283#else 284 return path; 285#endif 286} 287 288std::string ReadFileToString(const std::string &fileName) 289{ 290 std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str()); 291 std::ifstream inputString(resolvedPath, std::ios::in); 292 if (!inputString or !inputString.is_open()) { 293 return EMPTY_STRING; 294 } 295 std::istreambuf_iterator<char> firstIt = {inputString}; 296 std::istreambuf_iterator<char> lastIt = {}; 297 298 std::string content(firstIt, lastIt); 299 return content; 300} 301 302bool ReadFileToString(const std::string &fileName, std::string &fileData, size_t fileSize) 303{ 304 fileData.clear(); 305 std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str()); 306 OHOS::UniqueFd fd(open(resolvedPath.c_str(), O_RDONLY | O_BINARY)); 307 if (fileSize == 0) { 308 struct stat fileStat; 309 if (fstat(fd.Get(), &fileStat) != -1 && fileStat.st_size > 0) { 310 fileData.reserve(fileStat.st_size); 311 } 312 } else { 313 fileData.reserve(fileSize); 314 } 315 316 char buf[BUFSIZ] __attribute__((__uninitialized__)); 317 ssize_t readSize; 318 while ((readSize = read(fd.Get(), &buf[0], sizeof(buf))) > 0) { 319 fileData.append(buf, readSize); 320 } 321 return (readSize == 0) ? true : false; 322} 323 324bool WriteStringToFile(const std::string &fileName, const std::string &value) 325{ 326 std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str()); 327 std::ofstream output(resolvedPath, std::ios::out); 328 if (!output) { 329 return false; 330 } 331 output << value; 332 333 return output.good(); 334} 335 336bool IsRoot() 337{ 338#if defined(is_ohos) && is_ohos 339 std::string debugMode = "0"; 340 debugMode = OHOS::system::GetParameter("const.debuggable", debugMode); 341 return debugMode == "1"; 342#else 343 return true; 344#endif 345} 346 347bool PowerOfTwo(uint64_t n) 348{ 349 return n && (!(n & (n - 1))); 350} 351 352bool ReadIntFromProcFile(const std::string &path, int &value) 353{ 354 std::string s = ReadFileToString(path); 355 CHECK_TRUE(s.empty(), false, 0, ""); 356 value = std::stoi(s); 357 return true; 358} 359 360bool WriteIntToProcFile(const std::string &path, int value) 361{ 362 std::string s = std::to_string(value); 363 364 return WriteStringToFile(path, s); 365} 366 367// compress specified dataFile into gzip file 368bool CompressFile(const std::string &dataFile, const std::string &destFile) 369{ 370 std::string resolvedPath = CanonicalizeSpecPath(dataFile.c_str()); 371 FILE *fp = fopen(resolvedPath.c_str(), "rb"); 372 if (fp == nullptr) { 373 HLOGE("Fail to open data file %s", dataFile.c_str()); 374 perror("Fail to fopen(rb)"); 375 return false; 376 } 377 378 std::unique_ptr<gzFile_s, decltype(&gzclose)> fgz(gzopen(destFile.c_str(), "wb"), gzclose); 379 if (fgz == nullptr) { 380 HLOGE("Fail to call gzopen(%s)", destFile.c_str()); 381 fclose(fp); 382 return false; 383 } 384 385 std::vector<char> buf(COMPRESS_READ_BUF_SIZE); 386 size_t len = 0; 387 while ((len = fread(buf.data(), sizeof(uint8_t), buf.size(), fp))) { 388 if (gzwrite(fgz.get(), buf.data(), len) == 0) { 389 HLOGE("Fail to call gzwrite for %zu bytes", len); 390 fclose(fp); 391 return false; 392 } 393 } 394 if (!feof(fp)) { 395 if (ferror(fp) != 0) { 396 HLOGE("ferror return err"); 397 fclose(fp); 398 return false; 399 } 400 } 401 if (fclose(fp) < 0) { 402 return false; 403 } 404 return true; 405} 406 407// uncompress specified gzip file into dataFile 408bool UncompressFile(const std::string &gzipFile, const std::string &dataFile) 409{ 410 std::string resolvedPath = CanonicalizeSpecPath(dataFile.c_str()); 411 FILE *fp = fopen(resolvedPath.c_str(), "wb"); 412 if (fp == nullptr) { 413 HLOGE("Fail to open data file %s", dataFile.c_str()); 414 perror("Fail to fopen(rb)"); 415 return false; 416 } 417 std::unique_ptr<gzFile_s, decltype(&gzclose)> fgz(gzopen(gzipFile.c_str(), "rb"), gzclose); 418 if (fgz == nullptr) { 419 HLOGE("Fail to call gzopen(%s)", gzipFile.c_str()); 420 fclose(fp); 421 return false; 422 } 423 424 std::vector<char> buf(COMPRESS_READ_BUF_SIZE); 425 z_size_t len = 0; 426 while ((len = gzfread(buf.data(), sizeof(uint8_t), buf.size(), fgz.get()))) { 427 if (len != fwrite(buf.data(), sizeof(uint8_t), len, fp)) { 428 HLOGE("Fail to call fwrite for %zu bytes", len); 429 fclose(fp); 430 return false; 431 } 432 } 433 if (!gzeof(fgz.get())) { 434 int rc = 0; 435 const char *err = gzerror(fgz.get(), &rc); 436 if (rc != Z_OK) { 437 HLOGE("gzfread return %d:%s", rc, err); 438 fclose(fp); 439 return false; 440 } 441 } 442 if (fclose(fp) < 0) { 443 return false; 444 } 445 return true; 446} 447 448std::string &StringTrim(std::string &string) 449{ 450 if (!string.empty()) { 451 string.erase(0, string.find_first_not_of(" ")); 452 string.erase(string.find_last_not_of(" ") + 1); 453 } 454 return string; 455} 456 457std::vector<std::string> GetEntriesInDir(const std::string &basePath) 458{ 459 std::vector<std::string> result; 460 std::string resolvedPath = CanonicalizeSpecPath(basePath.c_str()); 461 CHECK_TRUE(resolvedPath.empty(), result, 0, ""); 462 DIR *dir = opendir(resolvedPath.c_str()); 463 CHECK_TRUE(dir == nullptr, result, 0, ""); 464 dirent *entry; 465 while ((entry = readdir(dir)) != nullptr) { 466 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { 467 continue; 468 } 469 result.push_back(entry->d_name); 470 } 471 closedir(dir); 472 return result; 473} 474 475std::vector<std::string> GetSubDirs(const std::string &basePath) 476{ 477 std::vector<std::string> entries = GetEntriesInDir(basePath); 478 std::vector<std::string> result = {}; 479 for (std::size_t index = 0; index < entries.size(); ++index) { 480 if (IsDir(basePath + "/" + entries[index])) { 481 result.push_back(std::move(entries[index])); 482 } 483 } 484 return result; 485} 486 487bool IsSameCommand(const std::string &cmdLine, const std::string &cmdName) 488{ 489 std::vector<std::string> cmdpaths = StringSplit(cmdLine, "/"); 490 if (!cmdpaths.empty()) { 491 if (strcmp(cmdpaths.back().c_str(), cmdName.c_str()) == 0) { 492 return true; 493 } 494 } 495 return false; 496} 497 498std::vector<pid_t> GetSubthreadIDs(const pid_t pid) 499{ 500 std::string path {"/proc/"}; 501 path += std::to_string(pid); 502 path += "/task/"; 503 auto tids = GetSubDirs(path); 504 std::vector<pid_t> res {}; 505 for (auto tidStr : tids) { 506 pid_t tid = static_cast<pid_t>(std::stoul(tidStr, nullptr)); 507 if (tid == pid) { 508 continue; 509 } 510 res.push_back(tid); 511 } 512 return res; 513} 514 515std::vector<pid_t> GetSubthreadIDs(const pid_t pid, std::map<pid_t, ThreadInfos> &thread_map) 516{ 517 std::string path {"/proc/"}; 518 path += std::to_string(pid); 519 path += "/task/"; 520 auto tids = GetSubDirs(path); 521 std::vector<pid_t> res{}; 522 for (auto tidStr : tids) { 523 ThreadInfos info; 524 pid_t tid = static_cast<pid_t>(std::stoul(tidStr, nullptr)); 525 info.tid = tid; 526 info.pid = pid; 527 thread_map[tid] = info; 528 res.push_back(tid); 529 } 530 return res; 531} 532 533bool StringStartsWith(const std::string &string, const std::string &with) 534{ 535 return string.find(with) == 0; 536} 537 538bool StringEndsWith(const std::string &string, const std::string &with) 539{ 540 if (string.empty()) { 541 // empty string only end with empty string 542 if (with.empty()) { 543 return true; 544 } else { 545 return false; 546 } 547 } 548 return string.rfind(with) == (string.length() - with.length()); 549} 550 551void HexDump(const void *buf, size_t size, size_t maxSize) 552{ 553 const unsigned char *byteBuf = static_cast<const unsigned char *>(buf); 554 const size_t dumpByteEachLine = 8; 555 size_t outputBytes = 0; 556 if (!maxSize) { 557 outputBytes = size; 558 } else { 559 outputBytes = std::min(size, maxSize); 560 } 561 562 for (size_t i = 0; i <= outputBytes; i += dumpByteEachLine) { 563 HLOGM(" %02zu: %s ", i, BufferToHexString(byteBuf, dumpByteEachLine).c_str()); 564 byteBuf += dumpByteEachLine; 565 } 566} 567 568std::string BufferToHexString(const std::vector<unsigned char> &vec) 569{ 570 return BufferToHexString(vec.data(), vec.size()); 571} 572 573std::string BufferToHexString(const unsigned char buf[], size_t size) 574{ 575 std::stringstream ss; 576 ss << size << ":"; 577 for (size_t i = 0; i < size; i++) { 578 ss << " 0x" << std::setfill('0') << std::setw(BYTE_PRINT_WIDTH) << std::hex 579 << (unsigned short)buf[i]; 580 } 581 return ss.str(); 582} 583 584void CollectPidsByAppname(std::set<pid_t> &pids, const std::string &appPackage) 585{ 586 const std::string basePath {"/proc/"}; 587 const std::string cmdline {"/cmdline"}; 588 std::vector<std::string> subDirs = GetSubDirs(basePath); 589 for (const auto &subDir : subDirs) { 590 if (!IsDigits(subDir)) { 591 continue; 592 } 593 std::string fileName {basePath + subDir + cmdline}; 594 if (IsSameCommand(ReadFileToString(fileName), appPackage)) { 595 pids.emplace(std::stoul(subDir, nullptr)); 596 } 597 } 598} 599 600bool IsRestarted(const std::string &appPackage) 601{ 602 printf("please restart %s for profiling within 30 seconds\n", appPackage.c_str()); 603 std::set<pid_t> oldPids {}; 604 std::set<pid_t> newPids {}; 605 std::vector<pid_t> intersection; 606 const auto startTime = steady_clock::now(); 607 const auto endTime = startTime + std::chrono::seconds(CHECK_TIMEOUT); 608 CollectPidsByAppname(oldPids, appPackage); 609 do { 610 CollectPidsByAppname(newPids, appPackage); 611 std::set_intersection(oldPids.begin(), oldPids.end(), 612 newPids.begin(), newPids.end(), std::back_insert_iterator(intersection)); 613 // app names are same, no intersection, means app restarted 614 CHECK_TRUE(intersection.empty(), true, 0, ""); 615 intersection.clear(); 616 newPids.clear(); 617 std::this_thread::sleep_for(milliseconds(CHECK_FREQUENCY)); 618 } while (steady_clock::now() < endTime); 619 printf("app %s was not stopped within 30 seconds\n", appPackage.c_str()); 620 return false; 621} 622 623pid_t GetAppPackagePid(const std::string &appPackage, const pid_t oldPid, const int checkAppMs, 624 const uint64_t waitAppTimeOut) 625{ 626 pid_t res {-1}; 627 const std::string basePath {"/proc/"}; 628 const std::string cmdline {"/cmdline"}; 629 const auto startTime = steady_clock::now(); 630 const auto endTime = startTime + std::chrono::seconds(waitAppTimeOut); 631 do { 632 std::vector<std::string> subDirs = GetSubDirs(basePath); 633 for (const auto &subDir : subDirs) { 634 if (!IsDigits(subDir)) { 635 continue; 636 } 637 std::string fileName {basePath + subDir + cmdline}; 638 if (IsSameCommand(ReadFileToString(fileName), appPackage)) { 639 res = std::stoul(subDir, nullptr); 640 HLOGD("[GetAppPackagePid]: get appid for %s is %d", appPackage.c_str(), res); 641 return res; 642 } 643 } 644 std::this_thread::sleep_for(milliseconds(checkAppMs)); 645 } while (steady_clock::now() < endTime); 646 647 return res; 648} 649 650bool CheckAppIsRunning (std::vector<pid_t> &selectPids, const std::string &appPackage, int checkAppMs) 651{ 652 if (!appPackage.empty()) { 653 pid_t appPid = GetAppPackagePid(appPackage, -1, checkAppMs, waitAppRunCheckTimeOut); 654 if (appPid <= 0) { 655 printf("app %s not running\n", appPackage.c_str()); 656 return false; 657 } 658 HLOGD("[CheckAppIsRunning] get appPid %d for app %s\n", appPid, appPackage.c_str()); 659 selectPids.push_back(appPid); 660 } 661 return true; 662} 663 664bool IsExistDebugByApp(const std::string& bundleName) 665{ 666 std::string bundleNameTmp = bundleName; 667 auto pos = bundleNameTmp.find(":"); 668 if (pos != std::string::npos) { 669 bundleNameTmp = bundleNameTmp.substr(0, pos); 670 } 671 if (!IsSupportNonDebuggableApp() && !bundleNameTmp.empty() && !IsDebugableApp(bundleNameTmp)) { 672 HLOGE("--app option only support debug application."); 673 printf("--app option only support debug application\n"); 674 return false; 675 } 676 return true; 677} 678 679bool IsExistDebugByPid(const std::vector<pid_t> &pids) 680{ 681 CHECK_TRUE(pids.empty(), true, 1, "IsExistDebugByPid: pids is empty."); 682 for (auto pid : pids) { 683 CHECK_TRUE(pid <= 0, false, LOG_TYPE_PRINTF, "Invalid -p value '%d', the pid should be larger than 0\n", pid); 684 std::string bundleName = GetProcessName(pid); 685 auto pos = bundleName.find(":"); 686 if (pos != std::string::npos) { 687 bundleName = bundleName.substr(0, pos); 688 } 689 if (!IsSupportNonDebuggableApp() && !IsDebugableApp(bundleName)) { 690 HLOGE("-p option only support debug application for %s", bundleName.c_str()); 691 printf("-p option only support debug application\n"); 692 return false; 693 } 694 } 695 return true; 696} 697 698bool IsDebugableApp(const std::string& bundleName) 699{ 700#if defined(is_ohos) && is_ohos && defined(BUNDLE_FRAMEWORK_ENABLE) 701 CHECK_TRUE(bundleName.empty(), false, LOG_TYPE_PRINTF, "bundleName is empty!\n"); 702 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 703 CHECK_TRUE(sam == nullptr, false, LOG_TYPE_PRINTF, "GetSystemAbilityManager failed!\n"); 704 sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); 705 CHECK_TRUE(remoteObject == nullptr, false, LOG_TYPE_PRINTF, "Get BundleMgr SA failed!\n"); 706 sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject); 707 CHECK_TRUE(proxy == nullptr, false, LOG_TYPE_PRINTF, "iface_cast failed!\n"); 708 AppExecFwk::ApplicationInfo appInfo; 709 bool ret = proxy->GetApplicationInfo(bundleName, AppExecFwk::GET_APPLICATION_INFO_WITH_DISABLE, 710 AppExecFwk::Constants::ANY_USERID, appInfo); 711 CHECK_TRUE(!ret, false, 1, "%s GetApplicationInfo failed!", bundleName.c_str()); 712 HLOGD("bundleName is %s,appProvisionType: %s", bundleName.c_str(), appInfo.appProvisionType.c_str()); 713 return appInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG; 714#else 715 return false; 716#endif 717} 718 719bool IsSupportNonDebuggableApp() 720{ 721 // root first 722 if (IsRoot()) { 723 return true; 724 } 725 // user mode 726 CHECK_TRUE(!IsBeta(), false, 0, ""); 727 // restricted aplication for beta 728 CHECK_TRUE(!IsAllowProfilingUid(), false, 0, ""); 729 return true; 730} 731 732const std::string GetUserType() 733{ 734#if defined(is_ohos) && is_ohos 735 std::string userType = OHOS::system::GetParameter(USER_TYPE_PARAM, USER_TYPE_PARAM_GET); 736 HLOGD("GetUserType: userType is %s", userType.c_str()); 737 return userType; 738#else 739 return ""; 740#endif 741} 742 743bool GetDeveloperMode() 744{ 745#if defined(is_ohos) && is_ohos 746 bool developerMode = OHOS::system::GetBoolParameter("const.security.developermode.state", false); 747 HLOGD("GetDeveloperMode: developerMode is %d", developerMode); 748 return developerMode; 749#else 750 return true; 751#endif 752} 753 754bool LittleMemory() 755{ 756 std::ifstream file("/proc/meminfo"); 757 std::string line; 758 while (getline(file, line)) { 759 if (line.find("MemTotal:") != std::string::npos) { 760 int memSize = stoi(line.substr(line.find(":") + 1)); 761 CHECK_TRUE(memSize < (LITTLE_MEMORY_SIZE * MULTIPLE_SIZE * MULTIPLE_SIZE), true, 0, ""); 762 } 763 } 764 return false; 765} 766 767// only for domestic beta 768bool IsBeta() 769{ 770 std::string userTypeRsp = GetUserType(); 771 if (userTypeRsp == USER_DOMESTIC_BETA) { 772 return true; 773 } 774 // default release when usertype param is invalid 775 CHECK_TRUE(userTypeRsp.empty(), true, 1, "GetUserType is empty [%s]", userTypeRsp.c_str()); 776 return false; 777} 778 779bool IsAllowProfilingUid() 780{ 781#if (defined(is_linux) && is_linux) || (defined(is_ohos) && is_ohos) 782 static unsigned int curUid = getuid(); 783 HLOGD("curUid is %d\n", curUid); 784 CHECK_TRUE(ALLOW_UIDS.find(curUid) != ALLOW_UIDS.end(), true, 0, ""); 785 return false; 786#else 787 return false; 788#endif 789} 790 791std::string GetProcessName(int pid) 792{ 793#if defined(is_ohos) && is_ohos 794 std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline"; 795 std::string bundleName = ReadFileToString(filePath); 796 return bundleName.substr(0, strlen(bundleName.c_str())); 797#else 798 return ""; 799#endif 800} 801 802bool NeedAdaptSandboxPath(char *filename, int pid, u16 &headerSize) 803{ 804 std::string oldFilename = filename; 805 if (oldFilename.find("/data/storage") == 0 && access(oldFilename.c_str(), F_OK) != 0) { 806 std::string newFilename = "/proc/" + std::to_string(pid) + "/root" + oldFilename; 807 (void)memset_s(filename, KILO, '\0', KILO); 808 if (strncpy_s(filename, KILO, newFilename.c_str(), newFilename.size()) != 0) { 809 HLOGD("strncpy_s recordMmap2 failed!"); 810 } 811 headerSize += newFilename.size() - oldFilename.size(); 812 return true; 813 } 814 return false; 815} 816 817bool NeedAdaptHMBundlePath(std::string& filename, const std::string& threadname) 818{ 819 static bool needCheck = true; 820 if (!needCheck) { 821 return false; 822 } 823 const std::string path = "/data/storage/el1/bundle"; 824 std::string newFileName = filename; 825 size_t pos = newFileName.find(path); 826 if (pos != std::string::npos) { 827 if (access(filename.c_str(), F_OK) != 0) { 828 const std::string newpath = "/data/app/el1/bundle/public/"; 829 // /data/storage/el1/bundle/libs/arm64/libentry.so 830 newFileName.replace(pos, path.length(), newpath + threadname); 831 if (access(newFileName.c_str(), F_OK) != 0) { 832 return false; 833 } 834 // /data/app/el1/bundle/public/<procname>/libs/arm64/libentry.so 835 filename = newFileName; 836 HLOGD("Fix hm bundle path to %s", filename.c_str()); 837 return true; 838 } else { 839 needCheck = false; 840 } 841 } 842 return false; 843} 844 845bool IsArkJsFile(const std::string& filepath) 846{ 847 return (StringEndsWith(filepath, ".hap") || 848 StringStartsWith(filepath, "[anon:ArkTS Code") || 849 StringEndsWith(filepath, ".hsp") || 850 StringEndsWith(filepath, ".abc") || 851 StringEndsWith(filepath, ".hqf")); 852} 853 854bool IsHiviewCall() 855{ 856#if defined(is_ohos) && is_ohos 857 pid_t ppid = syscall(SYS_getppid); 858 std::string cmdline = GetProcessName(ppid); 859 HLOGD("getppid is %d, cmdline is %s", ppid, cmdline.c_str()); 860 if (cmdline == HIVIEW_CMDLINE) { 861 HLOGD("hiview call"); 862 return true; 863 } 864 return false; 865#else 866 return false; 867#endif 868} 869 870bool IsApplicationEncryped(const int pid) 871{ 872#if defined(is_ohos) && is_ohos && defined(BUNDLE_FRAMEWORK_ENABLE) 873 CHECK_TRUE(pid <= 0, false, LOG_TYPE_PRINTF, "Invalid -p value '%d', the pid should be larger than 0\n", pid); 874 std::string bundleName = GetProcessName(pid); 875 CHECK_TRUE(bundleName.empty(), false, 1, "bundleName is empty,pid is %d", pid); 876 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 877 CHECK_TRUE(sam == nullptr, false, LOG_TYPE_PRINTF, "GetSystemAbilityManager failed!\n"); 878 sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); 879 CHECK_TRUE(remoteObject == nullptr, false, LOG_TYPE_PRINTF, "Get BundleMgr SA failed!\n"); 880 sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject); 881 CHECK_TRUE(proxy == nullptr, false, LOG_TYPE_PRINTF, "iface_cast failed!\n"); 882 883 AppExecFwk::ApplicationInfo appInfo; 884 bool ret = proxy->GetApplicationInfo(bundleName, AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, 885 AppExecFwk::Constants::ANY_USERID, appInfo); 886 CHECK_TRUE(!ret, false, 1, "%s:%s GetApplicationInfo failed!", __func__, bundleName.c_str()); 887 bool isEncrypted = (appInfo.applicationReservedFlag & 888 static_cast<uint32_t>(AppExecFwk::ApplicationReservedFlag::ENCRYPTED_APPLICATION)) != 0; 889 HLOGD("check application encryped.%d : %s, pid:%d", isEncrypted, bundleName.c_str(), pid); 890 return isEncrypted; 891#else 892 return false; 893#endif 894} 895} // namespace HiPerf 896} // namespace Developtools 897} // namespace OHOS 898