1 /*
2 * Copyright (C) 2025 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 <fstream>
17 #include <sstream>
18 #include "executor/memory/parse/parse_ashmem_info.h"
19 #include "executor/memory/memory_util.h"
20 #include "hilog_wrapper.h"
21 #include "util/file_utils.h"
22 #include "string_ex.h"
23
24 using namespace std;
25 namespace OHOS {
26 namespace HiviewDFX {
27 const int PHYSICAL_SIZE = 17; // 17 is the length of "physical size is "
28 const int START_POS = 1;
ParseAshmemInfo()29 ParseAshmemInfo::ParseAshmemInfo()
30 {
31 }
32
~ParseAshmemInfo()33 ParseAshmemInfo::~ParseAshmemInfo()
34 {
35 }
36
UpdateAshmemOverviewMap(const std::string & line,std::unordered_map<std::string,int64_t> & ashmemOverviewMap)37 void ParseAshmemInfo::UpdateAshmemOverviewMap(
38 const std::string &line, std::unordered_map<std::string, int64_t> &ashmemOverviewMap)
39 {
40 std::string tempLine = line;
41 // delete the whitespace characters at the end of the line
42 size_t lastNonSpace = tempLine.find_last_not_of(' ');
43 if (lastNonSpace != std::string::npos) {
44 tempLine.erase(lastNonSpace + START_POS);
45 }
46 size_t startPos = tempLine.find("[") + START_POS;
47 size_t endPos = tempLine.find("]", startPos);
48 if (startPos == std::string::npos || endPos == std::string::npos || endPos <= startPos) {
49 DUMPER_HILOGE(MODULE_SERVICE, "tempLine is error data, tempLine:%{public}s.", tempLine.c_str());
50 return;
51 }
52 std::string tmpProcessName = tempLine.substr(startPos, endPos - startPos);
53 size_t pos = tempLine.find("physical size is ");
54 if (pos == std::string::npos) {
55 DUMPER_HILOGE(MODULE_SERVICE, "tempLine not find [physical size is], tempLine:%{public}s.", tempLine.c_str());
56 return;
57 }
58 std::string physicalSize = tempLine.substr(pos + PHYSICAL_SIZE);
59 if (!IsNumericStr(physicalSize)) {
60 DUMPER_HILOGE(MODULE_SERVICE, "physicalSize is not number, physicalSize:%{public}s.", physicalSize.c_str());
61 return;
62 }
63 int64_t pss = 0;
64 if (!StringUtils::GetInstance().IsStringToIntSuccess(physicalSize, pss)) {
65 DUMPER_HILOGE(MODULE_SERVICE, "physicalSize is too big, physicalSize:%{public}s.", physicalSize.c_str());
66 return;
67 }
68 ashmemOverviewMap[tmpProcessName] = pss;
69 }
70
GetAshmemInfo(const int32_t & pid,pair<int,vector<string>> & result)71 bool ParseAshmemInfo::GetAshmemInfo(const int32_t &pid, pair<int, vector<string>> &result)
72 {
73 DUMPER_HILOGD(MODULE_SERVICE, "GetAshmemInfo begin, pid:%{public}d", pid);
74 bool inDetailSection = false;
75 std::string path = "/proc/ashmem_process_info";
76 std::string processName = "unknown";
77 std::string detailTitle = "";
78 std::vector<string> details;
79 std::unordered_map<std::string, int64_t> ashmemOverviewMap;
80 bool ret = FileUtils::GetInstance().LoadStringFromProcCb(path, false, true, [&](const string &line) -> void {
81 if (line.find("Total ashmem of") != std::string::npos) {
82 UpdateAshmemOverviewMap(line, ashmemOverviewMap);
83 }
84 if (line.find("Process_name") != std::string::npos) {
85 detailTitle = line;
86 inDetailSection = true;
87 return;
88 }
89 if (inDetailSection) {
90 std::istringstream lineStream(line);
91 int targetPid = 0;
92 std::string name;
93 lineStream >> name >> targetPid;
94 if (pid == targetPid) {
95 processName = name;
96 details.push_back(line);
97 }
98 }
99 });
100 if (details.empty()) {
101 DUMPER_HILOGE(MODULE_SERVICE, "detail ashmem is empty.");
102 return false;
103 }
104 details.insert(details.begin(), detailTitle);
105 if (ashmemOverviewMap.find(processName) == ashmemOverviewMap.end()) {
106 DUMPER_HILOGE(MODULE_SERVICE, "not find processName:%{public}s.", processName.c_str());
107 return false;
108 }
109 result.first = ashmemOverviewMap[processName] / static_cast<int64_t>(MemoryUtil::GetInstance().BYTE_TO_KB_); // KB
110 result.second = details;
111 DUMPER_HILOGD(MODULE_SERVICE, "GetAshmemInfo end, pid:%{public}d, ret:%{public}d", pid, ret);
112 return ret;
113 }
114 } // namespace HiviewDFX
115 } // namespace OHOS