• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "executor/memory/memory_info.h"
16 #include <algorithm>
17 #include <atomic>
18 #include <dlfcn.h>
19 #include <cinttypes>
20 #include <fstream>
21 #include <numeric>
22 #include <sstream>
23 #include <thread>
24 #include <v1_0/imemory_tracker_interface.h>
25 
26 #include "dump_common_utils.h"
27 #include "dump_utils.h"
28 #include "executor/memory/get_cma_info.h"
29 #include "executor/memory/get_hardware_info.h"
30 #include "executor/memory/get_kernel_info.h"
31 #include "executor/memory/get_process_info.h"
32 #include "executor/memory/get_ram_info.h"
33 #include "executor/memory/memory_util.h"
34 #include "executor/memory/parse/parse_ashmem_info.h"
35 #include "executor/memory/parse/parse_dmabuf_info.h"
36 #include "executor/memory/parse/parse_meminfo.h"
37 #include "executor/memory/parse/parse_smaps_rollup_info.h"
38 #include "executor/memory/parse/parse_smaps_info.h"
39 #include "file_ex.h"
40 #include "hdf_base.h"
41 #include "hilog_wrapper.h"
42 #ifdef HIDUMPER_MEMMGR_ENABLE
43 #include "mem_mgr_constant.h"
44 #endif
45 #include "securec.h"
46 #include "string_ex.h"
47 #include "util/string_utils.h"
48 #include "util/file_utils.h"
49 
50 using namespace std;
51 using namespace OHOS::HDI::Memorytracker::V1_0;
52 
53 namespace OHOS {
54 namespace HiviewDFX {
55 static const int PAGETAG_MIN_LEN = 2; // page tag min length
56 static const std::string LIB = "libai_mnt_client.so";
57 
58 static const std::string UNKNOWN_PROCESS = "unknown";
59 static const std::string PRE_BLANK = "   ";
60 static const std::string MEMORY_LINE = "-------------------------------[memory]-------------------------------";
61 constexpr char HIAI_MEM_INFO_FN[] = "HIAI_Memory_QueryAllUserAllocatedMemInfo";
62 using HiaiFunc = int (*)(MemInfoData::HiaiUserAllocatedMemInfo*, int, int*);
63 std::atomic<bool> g_isDumpMem = true;
64 constexpr int SECOND_TO_MILLISECONDS = 1000;
65 constexpr int MAX_STARS_NUM = 20;
66 constexpr int ONE_STAR = 1;
67 constexpr int APP_UID = 20000;
68 constexpr int LINE_SPACING = 8;
69 
MemoryInfo()70 MemoryInfo::MemoryInfo()
71 {
72     methodVec_.clear();
73     methodVec_.push_back(make_pair(MEMINFO_PSS,
74         bind(&MemoryInfo::SetPss, this, placeholders::_1, placeholders::_2)));
75     methodVec_.push_back(make_pair(MEMINFO_SHARED_CLEAN,
76         bind(&MemoryInfo::SetSharedClean, this, placeholders::_1, placeholders::_2)));
77     methodVec_.push_back(make_pair(MEMINFO_SHARED_DIRTY,
78         bind(&MemoryInfo::SetSharedDirty, this, placeholders::_1, placeholders::_2)));
79     methodVec_.push_back(make_pair(MEMINFO_PRIVATE_CLEAN,
80         bind(&MemoryInfo::SetPrivateClean, this, placeholders::_1, placeholders::_2)));
81     methodVec_.push_back(make_pair(MEMINFO_PRIVATE_DIRTY,
82         bind(&MemoryInfo::SetPrivateDirty, this, placeholders::_1, placeholders::_2)));
83     methodVec_.push_back(make_pair(MEMINFO_SWAP,
84         bind(&MemoryInfo::SetSwap, this, placeholders::_1, placeholders::_2)));
85     methodVec_.push_back(make_pair(MEMINFO_SWAP_PSS,
86         bind(&MemoryInfo::SetSwapPss, this, placeholders::_1, placeholders::_2)));
87     methodVec_.push_back(make_pair(MEMINFO_HEAP_SIZE,
88         bind(&MemoryInfo::SetHeapSize, this, placeholders::_1, placeholders::_2)));
89     methodVec_.push_back(make_pair(MEMINFO_HEAP_ALLOC,
90         bind(&MemoryInfo::SetHeapAlloc, this, placeholders::_1, placeholders::_2)));
91     methodVec_.push_back(make_pair(MEMINFO_HEAP_FREE,
92         bind(&MemoryInfo::SetHeapFree, this, placeholders::_1, placeholders::_2)));
93 }
94 
~MemoryInfo()95 MemoryInfo::~MemoryInfo()
96 {
97 }
98 
InsertMemoryTitle(StringMatrix result)99 void MemoryInfo::InsertMemoryTitle(StringMatrix result)
100 {
101     // Pss        Shared   ---- this line is line1
102     // Total      Clean    ---- this line is line2
103     // (KB)         (KB)    ---- this line is line3
104     // -----      ------   ---- this line is line4
105 
106     vector<string> line1;
107     vector<string> line2;
108     vector<string> line3;
109     vector<string> line4;
110 
111     string space = " ";
112     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, space);
113 
114     string separator = "-";
115     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, SEPARATOR_, false, separator);
116 
117     string unit = "(" + MemoryUtil::GetInstance().KB_UNIT_ + " )";
118     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, unit);
119 
120     // Add  spaces at the beginning of the line
121     line1.push_back(space + BLANK_);
122     line2.push_back(space + BLANK_);
123     line3.push_back(space + BLANK_);
124     line4.push_back(space);
125 
126     for (string str : MemoryFilter::GetInstance().TITLE_HAS_PID_) {
127         vector<string> types;
128         StringUtils::GetInstance().StringSplit(str, "_", types);
129         if (types.size() == TYPE_SIZE) {
130             string title1 = types.at(0);
131             StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, title1);
132             line1.push_back(title1 + BLANK_);
133 
134             string title2 = types.at(1);
135             StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, title2);
136             line2.push_back(title2 + BLANK_);
137             line3.push_back(unit + BLANK_);
138             line4.push_back(separator + SEPARATOR_);
139         }
140     }
141     result->push_back(line1);
142     result->push_back(line2);
143     result->push_back(line3);
144     result->push_back(line4);
145 }
146 
UpdateResult(const int32_t & pid,const unique_ptr<ProcessMemoryDetail> & processMemoryDetail,unique_ptr<MemoryDetail> & nativeHeapDetail,StringMatrix result)147 void MemoryInfo::UpdateResult(const int32_t& pid, const unique_ptr<ProcessMemoryDetail>& processMemoryDetail,
148     unique_ptr<MemoryDetail>& nativeHeapDetail, StringMatrix result)
149 {
150     unique_ptr<MallHeapInfo> mallocHeapInfo = make_unique<MallHeapInfo>();
151     unique_ptr<GetHeapInfo> getHeapInfo = make_unique<GetHeapInfo>();
152     getHeapInfo->GetMallocHeapInfo(pid, mallocHeapInfo);
153     unique_ptr<MemoryDetail> anonPageDetail = make_unique<MemoryDetail>();
154     unique_ptr<MemoryDetail> filePageDetail = make_unique<MemoryDetail>();
155     vector<MemoryDetail> memoryDetails = processMemoryDetail->details;
156     map<string, unique_ptr<MemoryDetail>> allDetailMap;
157     for (const auto& memoryDetail : memoryDetails) {
158         MemoryClass memoryClass = memoryDetail.memoryClass;
159         if (static_cast<int>(memoryClass) < 0 || static_cast<size_t>(memoryClass) > MEMORY_CLASS_VEC.size()) {
160             DUMPER_HILOGE(MODULE_SERVICE, "memoryClass:%{public}d is not exist", memoryClass);
161             continue;
162         }
163         string memoryClassStr = MEMORY_CLASS_VEC[static_cast<int>(memoryClass)];
164         unique_ptr<MemoryDetail> tempDetail = make_unique<MemoryDetail>(memoryDetail);
165         if (memoryClassStr == "graph") {
166             GetGraphicsMemoryByDetail(tempDetail, result);
167         } else if (memoryClassStr == MemoryFilter::GetInstance().NATIVE_HEAP_LABEL) {
168             nativeHeapDetail = make_unique<MemoryDetail>(memoryDetail);
169         } else if (memoryClassStr == MEMINFO_OTHER) {
170             UpdatePageDetail(anonPageDetail, filePageDetail, tempDetail);
171             tempDetail = std::move(anonPageDetail);
172             memoryClassStr = MEMINFO_ANONPAGE_OTHER;
173         }
174         auto it = std::find(MEMORY_PRINT_ORDER_VEC.begin(), MEMORY_PRINT_ORDER_VEC.end(), memoryClassStr);
175         if (it!= MEMORY_PRINT_ORDER_VEC.end()) {
176             allDetailMap[memoryClassStr] = std::move(tempDetail);
177         }
178     }
179     for (const auto &classStr : MEMORY_PRINT_ORDER_VEC) {
180         auto it = allDetailMap.find(classStr);
181         if (it != allDetailMap.end()) {
182             SetDetailRet(classStr, it->second, mallocHeapInfo, result);
183         }
184     }
185     SetDetailRet(MEMINFO_FILEPAGE_OTHER, filePageDetail, mallocHeapInfo, result);
186     UpdateTotalDetail(processMemoryDetail, mallocHeapInfo, result);
187 }
188 
UpdatePageDetail(std::unique_ptr<MemoryDetail> & anonPageDetail,std::unique_ptr<MemoryDetail> & filePageDetail,const std::unique_ptr<MemoryDetail> & tempDetail)189 void MemoryInfo::UpdatePageDetail(std::unique_ptr<MemoryDetail>& anonPageDetail,
190                                   std::unique_ptr<MemoryDetail>& filePageDetail,
191                                   const std::unique_ptr<MemoryDetail>& tempDetail)
192 {
193     if (!tempDetail) {
194         DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
195         return;
196     }
197     vector<MemoryItem> memoryItems = tempDetail->items;
198     for (const auto& memoryItem : memoryItems) {
199         int32_t iNode = memoryItem.iNode;
200         if (iNode == 0) {
201             anonPageDetail->totalPss += memoryItem.pss;
202             anonPageDetail->totalSharedClean += memoryItem.sharedClean;
203             anonPageDetail->totalSharedDirty += memoryItem.sharedDirty;
204             anonPageDetail->totalPrivateClean += memoryItem.privateClean;
205             anonPageDetail->totalPrivateDirty += memoryItem.privateDirty;
206             anonPageDetail->totalSwap += memoryItem.swap;
207             anonPageDetail->totalSwapPss += memoryItem.swapPss;
208         } else {
209             filePageDetail->totalPss += memoryItem.pss;
210             filePageDetail->totalSharedClean += memoryItem.sharedClean;
211             filePageDetail->totalSharedDirty += memoryItem.sharedDirty;
212             filePageDetail->totalPrivateClean += memoryItem.privateClean;
213             filePageDetail->totalPrivateDirty += memoryItem.privateDirty;
214             filePageDetail->totalSwap += memoryItem.swap;
215             filePageDetail->totalSwapPss += memoryItem.swapPss;
216         }
217     }
218 }
219 
SetDetailRet(const std::string & memoryClassStr,const std::unique_ptr<MemoryDetail> & detail,const std::unique_ptr<MallHeapInfo> & heapInfo,StringMatrix result)220 void MemoryInfo::SetDetailRet(const std::string& memoryClassStr, const std::unique_ptr<MemoryDetail>& detail,
221                               const std::unique_ptr<MallHeapInfo>& heapInfo, StringMatrix result)
222 {
223     if (!detail) {
224         DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
225         return;
226     }
227     vector<string> tempResult;
228     SetValueForRet(memoryClassStr, tempResult);
229     SetValueForRet(to_string(detail->totalPss), tempResult);
230     SetValueForRet(to_string(detail->totalSharedClean), tempResult);
231     SetValueForRet(to_string(detail->totalSharedDirty), tempResult);
232     SetValueForRet(to_string(detail->totalPrivateClean), tempResult);
233     SetValueForRet(to_string(detail->totalPrivateDirty), tempResult);
234     SetValueForRet(to_string(detail->totalSwap), tempResult);
235     SetValueForRet(to_string(detail->totalSwapPss), tempResult);
236     if (memoryClassStr == MemoryFilter::GetInstance().NATIVE_HEAP_LABEL) {
237         SetValueForRet(to_string(heapInfo->size), tempResult);
238         SetValueForRet(to_string(heapInfo->alloc), tempResult);
239         SetValueForRet(to_string(heapInfo->free), tempResult);
240     } else {
241         for (int i = 0; i < MALLOC_HEAP_TYPES; i++) {
242             SetValueForRet(ZERO, tempResult);
243         }
244     }
245     result->push_back(tempResult);
246 }
247 
SetValueForRet(const std::string & value,std::vector<std::string> & tempResult)248 void MemoryInfo::SetValueForRet(const std::string& value, std::vector<std::string>& tempResult)
249 {
250     std::string tempStr = value;
251     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, tempStr);
252     tempResult.push_back(tempStr + BLANK_);
253 }
254 
UpdateTotalDetail(const std::unique_ptr<ProcessMemoryDetail> & detail,const std::unique_ptr<MallHeapInfo> & heapInfo,StringMatrix result)255 void MemoryInfo::UpdateTotalDetail(const std::unique_ptr<ProcessMemoryDetail>& detail,
256                                    const std::unique_ptr<MallHeapInfo>& heapInfo, StringMatrix result)
257 {
258     if (!detail) {
259         DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
260         return;
261     }
262     vector<string> lines;
263     vector<string> values;
264     uint64_t totalPrivateDirty = static_cast<uint64_t>(detail->totalPrivateDirty) + graphicsMemory_.gl +
265         graphicsMemory_.graph;
266     currentPss_ = detail->totalAllPss;
267     MemoryUtil::GetInstance().SetMemTotalValue(MEMINFO_TOTAL, lines, values);
268     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalAllPss), lines, values);
269     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSharedClean), lines, values);
270     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSharedDirty), lines, values);
271     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalPrivateClean), lines, values);
272     MemoryUtil::GetInstance().SetMemTotalValue(to_string(totalPrivateDirty), lines, values);
273     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSwap), lines, values);
274     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSwapPss), lines, values);
275     MemoryUtil::GetInstance().SetMemTotalValue(to_string(heapInfo->size), lines, values);
276     MemoryUtil::GetInstance().SetMemTotalValue(to_string(heapInfo->alloc), lines, values);
277     MemoryUtil::GetInstance().SetMemTotalValue(to_string(heapInfo->free), lines, values);
278 
279     // delete the last separator
280     if (!lines.empty()) {
281         lines.pop_back();
282         string separator = "-";
283         StringUtils::GetInstance().SetWidth(LINE_WIDTH_, SEPARATOR_, false, separator);
284         lines.push_back(separator);
285     }
286     result->push_back(lines);
287     result->push_back(values);
288 }
289 
CalculateStars(const std::vector<int> & pssValues,int currentPSS)290 int MemoryInfo::CalculateStars(const std::vector<int>& pssValues, int currentPSS)
291 {
292     if (pssValues.empty()) {
293         return MAX_STARS_NUM;
294     }
295     auto [min_it, max_it] = std::minmax_element(pssValues.begin(), pssValues.end());
296     int minPSS = *min_it;
297     int maxPSS = *max_it;
298     if (maxPSS == minPSS) {
299         return MAX_STARS_NUM;
300     }
301     double stdValue = static_cast<double>(currentPSS - minPSS) / (maxPSS - minPSS);
302     return static_cast<int>(stdValue * (MAX_STARS_NUM - ONE_STAR) + ONE_STAR);
303 }
304 
WriteStdout(const std::string & s)305 void MemoryInfo::WriteStdout(const std::string& s)
306 {
307     write(rawParamFd_, s.c_str(), s.size());
308 }
309 
ClearPreviousLines(int lineCount)310 void MemoryInfo::ClearPreviousLines(int lineCount)
311 {
312     for (int i = 0; i < lineCount; ++i) {
313         WriteStdout("\033[F");
314         WriteStdout("\033[2K");
315     }
316 }
317 
GenerateLine(const std::vector<int> & pssValues,int index)318 std::string MemoryInfo::GenerateLine(const std::vector<int>& pssValues, int index)
319 {
320     DUMPER_HILOGI(MODULE_SERVICE, "pss:%{public}d", pssValues[index]);
321     int stars = CalculateStars(pssValues, pssValues[index]);
322     const int TOTAL_WIDTH = 26;
323     std::stringstream ss;
324     ss << std::string(stars, '*')
325        << std::string(TOTAL_WIDTH - stars, ' ')
326        << "times" << (index + 1) << ": PSS=" << pssValues[index] << "kB\n";
327     return ss.str();
328 }
329 
GenerateTimestamps(const std::vector<int> & pssValues)330 std::string MemoryInfo::GenerateTimestamps(const std::vector<int>& pssValues)
331 {
332     std::string endTime;
333     DumpCommonUtils::GetDateAndTime(DumpCommonUtils::GetMilliseconds() / SECOND_TO_MILLISECONDS, endTime);
334     int timeIndex = static_cast<int>(pssValues.size());
335     int maxMem = *std::max_element(pssValues.begin(), pssValues.end());
336     int changePss = 0;
337     if (pssValues.size() > 1) {
338         changePss = pssValues[pssValues.size() - 1] - pssValues[0];
339     }
340 
341     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, startTime_);
342     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, endTime);
343     string count = to_string(timeIndex);
344     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, count);
345     string maxMemStr = to_string(maxMem) + "kB";
346     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, maxMemStr);
347     string changePssStr = to_string(changePss) + "kB";
348     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, changePssStr);
349     return "StartTime           EndTime              Count                MaxMem              Change\n" +
350            startTime_ + endTime + " " + count + " " + maxMemStr + " " + changePssStr + "\n";
351 }
352 
CalculateMaxIdex(const std::vector<int> & pssValues,int * maxIndex)353 void MemoryInfo::CalculateMaxIdex(const std::vector<int>& pssValues, int *maxIndex)
354 {
355     const int minIndex = 5;
356     const int lastLines = 5;
357     for (int i = minIndex; i < static_cast<int>(pssValues.size()) - lastLines; ++i) {
358         if (pssValues[i] > pssValues[*maxIndex]) {
359             *maxIndex = i;
360         }
361     }
362 }
363 
PrintMemoryInfo(const std::vector<int> & pssValues,int * prevLineCount)364 void MemoryInfo::PrintMemoryInfo(const std::vector<int>& pssValues, int* prevLineCount)
365 {
366     static int lastMaxIndex = -1;
367     static int numHeaderLines = 2;
368     const int minIndex = 5;
369     const int lastLines = 5;
370     const int thresholdLines = 6;
371     const size_t maxPssValues = 10;
372     int currentLineCount = 0;
373     std::string output;
374 
375     output += GenerateTimestamps(pssValues);
376     currentLineCount += numHeaderLines;
377 
378     if (pssValues.size() <= maxPssValues) {
379         currentLineCount += static_cast<int>(pssValues.size());
380         for (size_t i = 0; i < pssValues.size(); ++i) {
381             output += GenerateLine(pssValues, static_cast<int>(i));
382         }
383     } else {
384         int maxIndex = 0;
385         CalculateMaxIdex(pssValues, &maxIndex);
386         for (int i = 0; i < minIndex; ++i) {
387             output += GenerateLine(pssValues, i);
388             currentLineCount++;
389         }
390 
391         if (maxIndex >= minIndex && maxIndex < static_cast<int>(pssValues.size()) - lastLines) {
392             if (maxIndex > minIndex) {
393                 output += "...\n";
394                 currentLineCount++;
395             }
396 
397             output += GenerateLine(pssValues, maxIndex);
398             currentLineCount++;
399 
400             if (maxIndex < static_cast<int>(pssValues.size()) - thresholdLines) {
401                 output += "...\n";
402                 currentLineCount++;
403             }
404 
405             lastMaxIndex = maxIndex;
406         } else {
407             output += "...\n";
408             currentLineCount++;
409         }
410 
411         for (int i = static_cast<int>(pssValues.size()) - lastLines; i < static_cast<int>(pssValues.size()); ++i) {
412             output += GenerateLine(pssValues, i);
413             currentLineCount++;
414         }
415     }
416 
417     if (*prevLineCount > 0) {
418         ClearPreviousLines(*prevLineCount);
419     }
420 
421     WriteStdout(output);
422     *prevLineCount = currentLineCount;
423 }
424 
SetReceivedSigInt(bool isReceivedSigInt)425 void MemoryInfo::SetReceivedSigInt(bool isReceivedSigInt)
426 {
427     DUMPER_HILOGI(MODULE_SERVICE, "isReceivedSigInt: %{public}d", isReceivedSigInt);
428     g_isDumpMem = !isReceivedSigInt;
429 }
430 
RedirectMemoryInfo(int timeIndex,StringMatrix result)431 void MemoryInfo::RedirectMemoryInfo(int timeIndex, StringMatrix result)
432 {
433     int redirectFd = DumpUtils::FdToWrite("/data/log/hidumper/record_mem.txt");
434     if (redirectFd <= -1) {
435         DUMPER_HILOGE(MODULE_COMMON, "write to record_mem.txt failed");
436         return;
437     }
438     string timeTitle = "\ntimes:" + to_string(timeIndex) + "\n";
439     write(redirectFd, timeTitle.c_str(), strlen(timeTitle.c_str()));
440     for (size_t i = 0; i < result->size(); i++) {
441         std::vector<std::string> line = result->at(i);
442         for (size_t j = 0; j < line.size(); j++) {
443             std::string str = line[j];
444             if ((j == (line.size() - 1)) && (str.find("\n") == std::string::npos)) {
445                 str = str + "\n";
446             }
447             if (write(redirectFd, str.c_str(), strlen(str.c_str())) == -1) {
448                 DUMPER_HILOGE(MODULE_COMMON, "write to rawParamFd failed, errno: %{public}d", errno);
449             }
450         }
451     }
452     close(redirectFd);
453 }
454 
GetMemoryInfoByTimeInterval(int fd,const int32_t & pid,const int32_t & timeInterval)455 void MemoryInfo::GetMemoryInfoByTimeInterval(int fd, const int32_t &pid, const int32_t &timeInterval)
456 {
457     std::lock_guard<std::mutex> lock(timeIntervalMutex_);
458     rawParamFd_ = fd;
459     (void)dprintf(rawParamFd_, "%s\n\n", MEMORY_LINE.c_str());
460     DumpCommonUtils::GetDateAndTime(DumpCommonUtils::GetMilliseconds() / SECOND_TO_MILLISECONDS, startTime_);
461     DUMPER_HILOGI(MODULE_SERVICE, "GetMemoryInfoByTimeInterval timeInterval:%{public}d", timeInterval);
462     std::vector<int> pssValues;
463     int prevLineCount = 0;
464     while (g_isDumpMem) {
465         StringMatrix result = std::make_shared<std::vector<std::vector<std::string>>>();
466         GetMemoryInfoByPid(pid, result, false, false);
467         pssValues.push_back(static_cast<int>(currentPss_));
468         PrintMemoryInfo(pssValues, &prevLineCount);
469         RedirectMemoryInfo(static_cast<int>(pssValues.size()), result);
470         sleep(timeInterval);
471     }
472     g_isDumpMem = true;
473     DUMPER_HILOGI(MODULE_SERVICE, "GetMemoryInfoByTimeInterval timeInterval:%{public}d end", timeInterval);
474 }
475 
GetMemoryInfoByPid(const int32_t & pid,StringMatrix result,bool showAshmem,bool showDmaBuf)476 bool MemoryInfo::GetMemoryInfoByPid(const int32_t &pid, StringMatrix result, bool showAshmem, bool showDmaBuf)
477 {
478     std::lock_guard<std::mutex> lock(mutex_);
479     InsertMemoryTitle(result);
480     GetResult(pid, result);
481     GetPurgByPid(pid, result);
482     GetDma(graphicsMemory_.graph, result);
483     GetDmaBuf(pid, result, showDmaBuf);
484     GetHiaiServerIon(pid, result);
485     GetAshmem(pid, result, showAshmem);
486     return true;
487 }
488 
GetResult(const int32_t & pid,StringMatrix result)489 void MemoryInfo::GetResult(const int32_t& pid, StringMatrix result)
490 {
491     DUMPER_HILOGD(MODULE_SERVICE, "CollectProcessMemoryDetail pid:%{public}d start", pid);
492     std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create();
493     CollectResult<ProcessMemoryDetail> collectRet;
494     collectRet = collector->CollectProcessMemoryDetail(pid, GraphicMemOption::LOW_LATENCY);
495     if (collectRet.retCode != UCollect::UcError::SUCCESS) {
496         DUMPER_HILOGE(MODULE_SERVICE, "collect process memory error, ret:%{public}d", collectRet.retCode);
497         return;
498     }
499     unique_ptr<ProcessMemoryDetail> processMemoryDetail = make_unique<ProcessMemoryDetail>(collectRet.data);
500     if (!processMemoryDetail) {
501         DUMPER_HILOGE(MODULE_SERVICE, "processMemoryDetail is nullptr");
502         return;
503     }
504     DUMPER_HILOGD(MODULE_SERVICE, "CollectProcessMemoryDetail pid:%{public}d end", pid);
505     unique_ptr<MemoryDetail> nativeHeapDetail = {nullptr};
506     UpdateResult(pid, processMemoryDetail, nativeHeapDetail, result);
507     GetNativeHeap(nativeHeapDetail, result);
508 }
509 
GetGraphicsMemoryByDetail(const std::unique_ptr<MemoryDetail> & detail,StringMatrix result)510 void MemoryInfo::GetGraphicsMemoryByDetail(const std::unique_ptr<MemoryDetail>& detail, StringMatrix result)
511 {
512     if (!detail) {
513         DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
514         return;
515     }
516     vector<MemoryItem> memoryItems = detail->items;
517     for (const auto& memoryItem : memoryItems) {
518         MemoryItemType memoryItemType = memoryItem.type;
519         auto info = GRAPHIC_MAP.find(memoryItemType);
520         if (info == GRAPHIC_MAP.end()) {
521             DUMPER_HILOGE(MODULE_SERVICE, "memoryItemType = %{public}d is not exist", memoryItemType);
522             continue;
523         }
524         string type = info->second;
525         if (type == MemoryFilter::GetInstance().GL_OUT_LABEL) {
526             graphicsMemory_.gl = memoryItem.pss;
527         } else if (type == MemoryFilter::GetInstance().GRAPH_OUT_LABEL) {
528             graphicsMemory_.graph = memoryItem.pss;
529         }
530     }
531     UpdateGraphicsMemoryRet(MemoryFilter::GetInstance().GL_OUT_LABEL, graphicsMemory_.gl, result);
532     UpdateGraphicsMemoryRet(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, graphicsMemory_.graph, result);
533 }
534 
UpdateGraphicsMemoryRet(const string & title,const uint64_t & value,StringMatrix result)535 void MemoryInfo::UpdateGraphicsMemoryRet(const string& title, const uint64_t& value, StringMatrix result)
536 {
537     map<string, uint64_t> valueMap;
538     valueMap.insert(pair<string, uint64_t>(MEMINFO_PSS, value));
539     valueMap.insert(pair<string, uint64_t>(MEMINFO_PRIVATE_DIRTY, value));
540     vector<string> tempResult;
541     string tempTitle = title;
542     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, tempTitle);
543     tempResult.push_back(tempTitle + BLANK_);
544     for (const auto &tag : MemoryFilter::GetInstance().VALUE_WITH_PID) {
545         auto it = valueMap.find(tag);
546         string value = ZERO;
547         if (it != valueMap.end()) {
548             value = to_string(it->second);
549         }
550         StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, value);
551         tempResult.push_back(value + BLANK_);
552     }
553     result->push_back(tempResult);
554 }
555 
AddKbUnit(const uint64_t & value) const556 string MemoryInfo::AddKbUnit(const uint64_t &value) const
557 {
558     return to_string(value) + MemoryUtil::GetInstance().KB_UNIT_;
559 }
560 
GetSmapsInfoNoPid(const int32_t & pid,GroupMap & result)561 bool MemoryInfo::GetSmapsInfoNoPid(const int32_t &pid, GroupMap &result)
562 {
563     GroupMap NativeMap;
564     unique_ptr<ParseSmapsInfo> parseSmapsInfo = make_unique<ParseSmapsInfo>();
565     return parseSmapsInfo->GetInfo(MemoryFilter::NOT_SPECIFIED_PID, pid, NativeMap, result);
566 }
567 
GetMeminfo(ValueMap & result)568 bool MemoryInfo::GetMeminfo(ValueMap &result)
569 {
570     unique_ptr<ParseMeminfo> parseMeminfo = make_unique<ParseMeminfo>();
571     return parseMeminfo->GetMeminfo(result);
572 }
573 
GetHardWareUsage(StringMatrix result)574 bool MemoryInfo::GetHardWareUsage(StringMatrix result)
575 {
576     uint64_t value;
577     unique_ptr<GetHardwareInfo> getHardwareInfo = make_unique<GetHardwareInfo>();
578     if (getHardwareInfo->GetHardwareUsage(value)) {
579         string title = "Hardware Usage:";
580         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
581         SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
582         return true;
583     }
584     return false;
585 }
586 
GetCMAUsage(StringMatrix result)587 bool MemoryInfo::GetCMAUsage(StringMatrix result)
588 {
589     uint64_t value = 0;
590     unique_ptr<GetCMAInfo> getCMAInfo = make_unique<GetCMAInfo>();
591     bool success = getCMAInfo->GetUsed(value);
592     if (success) {
593         string title = "CMA Usage:";
594         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
595         SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
596     }
597     return success;
598 }
599 
GetKernelUsage(const ValueMap & infos,StringMatrix result)600 bool MemoryInfo::GetKernelUsage(const ValueMap &infos, StringMatrix result)
601 {
602     uint64_t value = 0;
603     unique_ptr<GetKernelInfo> getGetKernelInfo = make_unique<GetKernelInfo>();
604     bool success = getGetKernelInfo->GetKernel(infos, value);
605     if (success) {
606         string title = "Kernel Usage:";
607         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
608         SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
609     }
610     return success;
611 }
612 
GetProcesses(const GroupMap & infos,StringMatrix result)613 void MemoryInfo::GetProcesses(const GroupMap &infos, StringMatrix result)
614 {
615     uint64_t value = 0;
616 
617     unique_ptr<GetProcessInfo> getProcessInfo = make_unique<GetProcessInfo>();
618     value = getProcessInfo->GetProcess(infos);
619 
620     string title = "Processes Usage:";
621     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
622     SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
623 }
624 
GetPssTotal(const GroupMap & infos,StringMatrix result)625 void MemoryInfo::GetPssTotal(const GroupMap &infos, StringMatrix result)
626 {
627     SaveStringToFd(rawParamFd_, "Total Pss by Category:\n");
628     vector<pair<string, uint64_t>> filePage;
629     vector<pair<string, uint64_t>> anonPage;
630     for (const auto &info : infos) {
631         vector<string> pageTag;
632         StringUtils::GetInstance().StringSplit(info.first, "#", pageTag);
633         if (pageTag.size() < PAGETAG_MIN_LEN) {
634             DUMPER_HILOGE(MODULE_COMMON, "Infos are invalid, info.first: %{public}s", info.first.c_str());
635             continue;
636         }
637         string group = pageTag[1];
638         auto &valueMap = info.second;
639         uint64_t pssValue = 0;
640         for (const auto &str : MemoryFilter::GetInstance().CALC_PSS_TOTAL_) {
641             auto it = valueMap.find(str);
642             if (it != valueMap.end()) {
643                 pssValue += it->second;
644             }
645         }
646 
647         if (pageTag[0] == MemoryFilter::GetInstance().FILE_PAGE_TAG) {
648             filePage.push_back(make_pair(group, pssValue));
649         } else {
650             anonPage.push_back(make_pair(group, pssValue));
651         }
652     }
653     PairToStringMatrix(MemoryFilter::GetInstance().FILE_PAGE_TAG, filePage, result);
654     PairToStringMatrix(MemoryFilter::GetInstance().ANON_PAGE_TAG, anonPage, result);
655 
656     vector<pair<string, uint64_t>> gpuValue;
657     gpuValue.push_back(make_pair(MemoryFilter::GetInstance().GL_OUT_LABEL, totalGL_));
658     PairToStringMatrix(MemoryFilter::GetInstance().GPU_TAG, gpuValue, result);
659 
660     vector<pair<string, uint64_t>> graphValue;
661     graphValue.push_back(make_pair(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, totalGraph_));
662     PairToStringMatrix(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, graphValue, result);
663 
664     vector<pair<string, uint64_t>> dmaValue;
665     dmaValue.push_back(make_pair(MemoryFilter::GetInstance().DMA_OUT_LABEL, totalDma_));
666     PairToStringMatrix(MemoryFilter::GetInstance().DMA_TAG, dmaValue, result);
667 }
668 
PairToStringMatrix(const string & titleStr,vector<pair<string,uint64_t>> & vec,StringMatrix result)669 void MemoryInfo::PairToStringMatrix(const string &titleStr, vector<pair<string, uint64_t>> &vec, StringMatrix result)
670 {
671     uint64_t totalPss = accumulate(vec.begin(), vec.end(), (uint64_t)0, [] (uint64_t a, pair<string, uint64_t> &b) {
672         return a + b.second;
673     });
674     SaveStringToFd(rawParamFd_, titleStr + "(" + AddKbUnit(totalPss) + "):\n");
675 
676     std::sort(vec.begin(), vec.end(),
677         [] (pair<string, uint64_t> &left, pair<string, uint64_t> &right) {
678         return right.second < left.second;
679     });
680     for (const auto &pair : vec) {
681         string pssStr = AddKbUnit(pair.second);
682         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, pssStr);
683         SaveStringToFd(rawParamFd_, pssStr + " : " + pair.first + "\n");
684     }
685 }
686 
GetRamUsage(const GroupMap & smapsinfos,const ValueMap & meminfo,StringMatrix result)687 void MemoryInfo::GetRamUsage(const GroupMap &smapsinfos, const ValueMap &meminfo, StringMatrix result)
688 {
689     unique_ptr<GetRamInfo> getRamInfo = make_unique<GetRamInfo>();
690     GetRamInfo::Ram ram = getRamInfo->GetRam(smapsinfos, meminfo);
691 
692     string totalTitle = "Total RAM:";
693     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalTitle);
694     SaveStringToFd(rawParamFd_, totalTitle + AddKbUnit(ram.total) + "\n");
695 
696     string freeTitle = "Free RAM:";
697     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, freeTitle);
698     SaveStringToFd(rawParamFd_, freeTitle + AddKbUnit(ram.free) +
699         " (" + to_string(ram.cachedInfo) + " cached + " + to_string(ram.freeInfo) + " free)\n");
700 
701     string usedTitle = "Used RAM:";
702     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, usedTitle);
703     SaveStringToFd(rawParamFd_, usedTitle + AddKbUnit(ram.used) +
704         " (" + to_string(ram.totalPss) + " total pss + " + to_string(ram.kernelUsed) + " kernel)\n");
705 
706     string lostTitle = "Lost RAM:";
707     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, lostTitle);
708     SaveStringToFd(rawParamFd_, lostTitle + to_string(ram.lost) + MemoryUtil::GetInstance().KB_UNIT_ + "\n");
709 }
710 
GetPurgTotal(const ValueMap & meminfo,StringMatrix result)711 void MemoryInfo::GetPurgTotal(const ValueMap &meminfo, StringMatrix result)
712 {
713     SaveStringToFd(rawParamFd_, "Total Purgeable:\n");
714 
715     uint64_t purgSumTotal = 0;
716     uint64_t purgPinTotal = 0;
717     auto purgSumActive = meminfo.find(MemoryFilter::GetInstance().PURG_SUM[0]);
718     auto purgSumInactive = meminfo.find(MemoryFilter::GetInstance().PURG_SUM[1]);
719     auto purgPinPined = meminfo.find(MemoryFilter::GetInstance().PURG_PIN[0]);
720     if (purgSumActive == meminfo.end() || purgSumInactive == meminfo.end() || purgPinPined == meminfo.end()) {
721         DUMPER_HILOGE(MODULE_SERVICE, "fail to get purg info \n");
722     } else {
723         purgSumTotal = purgSumActive->second + purgSumInactive->second;
724         purgPinTotal = purgPinPined->second;
725     }
726 
727     string totalPurgSumTitle = "Total PurgSum:";
728     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalPurgSumTitle);
729     SaveStringToFd(rawParamFd_, totalPurgSumTitle + AddKbUnit(purgSumTotal) + "\n");
730 
731     string totalPurgPinTitle = "Total PurgPin:";
732     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalPurgPinTitle);
733     SaveStringToFd(rawParamFd_, totalPurgPinTitle + AddKbUnit(purgPinTotal) + "\n");
734 }
735 
GetPurgByPid(const int32_t & pid,StringMatrix result)736 void MemoryInfo::GetPurgByPid(const int32_t &pid, StringMatrix result)
737 {
738     AddBlankLine(result);
739     vector<string> title;
740     title.push_back("Purgeable:");
741     result->push_back(title);
742 
743     vector<string> purgSum;
744     string purgSumTitle = MemoryFilter::GetInstance().PURGSUM_OUT_LABEL + ":";
745     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, purgSumTitle);
746     purgSum.push_back(purgSumTitle);
747     purgSum.push_back(AddKbUnit(GetProcValue(pid, MemoryFilter::GetInstance().PURGSUM_OUT_LABEL)));
748     result->push_back(purgSum);
749 
750     vector<string> purgPin;
751     string purgPinTitle = MemoryFilter::GetInstance().PURGPIN_OUT_LABEL + ":";
752     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, purgPinTitle);
753     purgPin.push_back(purgPinTitle);
754     purgPin.push_back(AddKbUnit(GetProcValue(pid, MemoryFilter::GetInstance().PURGPIN_OUT_LABEL)));
755     result->push_back(purgPin);
756 }
757 
GetNativeHeap(const std::unique_ptr<MemoryDetail> & detail,StringMatrix result)758 void MemoryInfo::GetNativeHeap(const std::unique_ptr<MemoryDetail>& detail, StringMatrix result)
759 {
760     if (!detail) {
761         DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
762         return;
763     }
764     AddBlankLine(result);
765     vector<string> title;
766     title.push_back(MemoryFilter::GetInstance().NATIVE_HEAP_LABEL + ":");
767     result->push_back(title);
768 
769     vector<MemoryItem> memoryItems = detail->items;
770     for (const auto& memoryItem : memoryItems) {
771         MemoryItemType memoryItemType = memoryItem.type;
772         auto info = NATIVE_HEAP_MAP.find(memoryItemType);
773         if (info == NATIVE_HEAP_MAP.end()) {
774             DUMPER_HILOGE(MODULE_SERVICE, "memoryItemType = %{public}d is not exist", memoryItemType);
775             continue;
776         }
777         string type = info->second;
778         auto it = memoryItemMap_.find(type);
779         if (it == memoryItemMap_.end()) {
780             memoryItemMap_.insert(pair<string, MemoryItem>(type, memoryItem));
781         } else {
782             it->second.pss += memoryItem.pss;
783             it->second.sharedClean += memoryItem.sharedClean;
784             it->second.sharedDirty += memoryItem.sharedDirty;
785             it->second.privateClean += memoryItem.privateClean;
786             it->second.privateDirty += memoryItem.privateDirty;
787             it->second.swap += memoryItem.swap;
788             it->second.swapPss += memoryItem.swapPss;
789         }
790     }
791     for (const auto& type: NATIVE_HEAP_TAG) {
792         auto it = memoryItemMap_.find(type);
793         if (it == memoryItemMap_.end()) {
794             continue;
795         }
796         string heapTitle = it->first;
797         unique_ptr<MemoryItem> item = make_unique<MemoryItem>(it->second);
798         SetNativeDetailRet(type, item, result);
799     }
800 }
801 
SetNativeDetailRet(const std::string & nativeClassStr,const std::unique_ptr<MemoryItem> & item,StringMatrix result)802 void MemoryInfo::SetNativeDetailRet(const std::string& nativeClassStr, const std::unique_ptr<MemoryItem>& item,
803                                     StringMatrix result)
804 {
805     vector<string> heap;
806     string heapTitle = nativeClassStr + ":";
807     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, heapTitle);
808     heap.push_back(heapTitle);
809     SetValueForRet(to_string(item->pss), heap);
810     SetValueForRet(to_string(item->sharedClean), heap);
811     SetValueForRet(to_string(item->sharedDirty), heap);
812     SetValueForRet(to_string(item->privateClean), heap);
813     SetValueForRet(to_string(item->privateDirty), heap);
814     SetValueForRet(to_string(item->swap), heap);
815     SetValueForRet(to_string(item->swapPss), heap);
816     for (int i = 0; i < MALLOC_HEAP_TYPES; i++) {
817         SetValueForRet(ZERO, heap);
818     }
819     result->push_back(heap);
820 }
821 
GetDma(const uint64_t & dmaValue,StringMatrix result)822 void MemoryInfo::GetDma(const uint64_t& dmaValue, StringMatrix result)
823 {
824     AddBlankLine(result);
825     vector<string> title;
826     title.push_back(MemoryFilter::GetInstance().DMA_TAG + ":");
827     result->push_back(title);
828 
829     vector<string> dma;
830     string dmaTitle = MemoryFilter::GetInstance().DMA_OUT_LABEL + ":";
831     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, dmaTitle);
832     dma.push_back(dmaTitle);
833     dma.push_back(to_string(dmaValue) + MemoryUtil::GetInstance().KB_UNIT_);
834     result->push_back(dma);
835 }
836 
GetHiaiServerIon(const int32_t & pid,StringMatrix result)837 void MemoryInfo::GetHiaiServerIon(const int32_t &pid, StringMatrix result)
838 {
839     if (GetProcName(pid) != "hiaiserver") {
840         return;
841     }
842     void *handle = dlopen(LIB.c_str(), RTLD_LAZY);
843     if (handle == nullptr) {
844         DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s.", LIB.c_str());
845         return;
846     }
847     HiaiFunc pfn = reinterpret_cast<HiaiFunc>(dlsym(handle, HIAI_MEM_INFO_FN));
848     if (pfn == nullptr) {
849         DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym %{public}s.", HIAI_MEM_INFO_FN);
850         dlclose(handle);
851         return;
852     }
853     MemInfoData::HiaiUserAllocatedMemInfo memInfos[HIAI_MAX_QUERIED_USER_MEMINFO_LIMIT] = {};
854 
855     int realSize = 0;
856     pfn(memInfos, HIAI_MAX_QUERIED_USER_MEMINFO_LIMIT, &realSize);
857     if (realSize > 0) {
858         AddBlankLine(result);
859         vector<string> vecIon;
860         vecIon.push_back("HIAIServer ION:\n");
861         for (int i = 0; i < realSize; i++) {
862             vecIon.push_back(GetProcName(memInfos[i].pid) + "(" + to_string(memInfos[i].pid) + "):" +
863                              to_string(memInfos[i].size / BYTE_PER_KB) + " kB\n");
864         }
865         result->push_back(vecIon);
866     }
867     dlclose(handle);
868 }
869 
GetAshmem(const int32_t & pid,StringMatrix result,bool showAshmem)870 void MemoryInfo::GetAshmem(const int32_t &pid, StringMatrix result, bool showAshmem)
871 {
872     std::pair<int, std::vector<std::string>> ashmemInfo;
873     unique_ptr<ParseAshmemInfo> parseAshmeminfo = make_unique<ParseAshmemInfo>();
874     if (!parseAshmeminfo->GetAshmemInfo(pid, ashmemInfo)) {
875         DUMPER_HILOGE(MODULE_SERVICE, "GetAshmemInfo error");
876         return;
877     }
878     if (ashmemInfo.second.size() == 0) {
879         DUMPER_HILOGE(MODULE_SERVICE, "no detail ashmem info.");
880         return;
881     }
882     AddBlankLine(result);
883     vector<string> title;
884     title.push_back("Ashmem:");
885     result->push_back(title);
886     vector<string> totalAshmemVec;
887     totalAshmemVec.push_back("Total Ashmem:" + to_string(ashmemInfo.first) + MemoryUtil::GetInstance().KB_UNIT_);
888     result->push_back(totalAshmemVec);
889     if (showAshmem) {
890         for (auto detailInfo : ashmemInfo.second) {
891             vector<string> tempResult;
892             tempResult.push_back(detailInfo);
893             result->push_back(tempResult);
894         }
895     }
896 }
897 
GetDmaBuf(const int32_t & pid,StringMatrix result,bool showDmaBuf)898 void MemoryInfo::GetDmaBuf(const int32_t &pid, StringMatrix result, bool showDmaBuf)
899 {
900     if (!showDmaBuf) {
901         DUMPER_HILOGD(MODULE_SERVICE, "showDmaBuf is false, skip GetDmaBuf");
902         return;
903     }
904     int32_t uid = GetProcUid(pid);
905     if (uid < APP_UID) {
906         DUMPER_HILOGD(MODULE_SERVICE, "Uid Verification failed for uid: %{public}d", uid);
907         return;
908     }
909     std::vector<std::string> dmabufInfo;
910     std::vector<std::string> titles;
911     unordered_map<std::string, int> headerMap;
912     vector<int> columnWidths;
913     unique_ptr<ParseDmaBufInfo> parseDmaBufInfo = make_unique<ParseDmaBufInfo>();
914     if (!parseDmaBufInfo->GetDmaBufInfo(pid, dmabufInfo, headerMap, columnWidths, titles)) {
915         DUMPER_HILOGE(MODULE_SERVICE, "GetDmaBufInfo error");
916         return;
917     }
918     const std::unordered_set<std::string> exTitles = { "can_reclaim", "is_reclaim" };
919     for (const auto& dmabuf : dmabufInfo) {
920         std::istringstream ss(dmabuf);
921         std::ostringstream oss;
922         for (const auto& title : titles) {
923             std::string value;
924             if (!(ss >> value)) {
925                 value = "NULL";
926             }
927             if (exTitles.find(title) != exTitles.end()) {
928                 continue;
929             }
930             int width = columnWidths[headerMap[title]];
931             oss << std::left << std::setw(width + LINE_SPACING) << value;
932         }
933         vector<string> tempResult;
934         tempResult.push_back(oss.str());
935         result->push_back(tempResult);
936     }
937 }
938 
GetRamCategory(const GroupMap & smapsInfos,const ValueMap & meminfos,StringMatrix result)939 void MemoryInfo::GetRamCategory(const GroupMap &smapsInfos, const ValueMap &meminfos, StringMatrix result)
940 {
941     SaveStringToFd(rawParamFd_, "Total RAM by Category:\n");
942 
943     bool hardWareSuccess = GetHardWareUsage(result);
944     if (!hardWareSuccess) {
945         DUMPER_HILOGE(MODULE_SERVICE, "Get hardWare usage fail.\n");
946     }
947 
948     bool cmaSuccess = GetCMAUsage(result);
949     if (!cmaSuccess) {
950         DUMPER_HILOGE(MODULE_SERVICE, "Get CMA fail.\n");
951     }
952 
953     bool kernelSuccess = GetKernelUsage(meminfos, result);
954     if (!kernelSuccess) {
955         DUMPER_HILOGE(MODULE_SERVICE, "Get kernel usage fail.\n");
956     }
957 
958     GetProcesses(smapsInfos, result);
959 }
960 
AddBlankLine(StringMatrix result)961 void MemoryInfo::AddBlankLine(StringMatrix result)
962 {
963     vector<string> blank;
964     blank.push_back("\n");
965     result->push_back(blank);
966 }
967 
GetProcName(const int32_t & pid)968 string MemoryInfo::GetProcName(const int32_t &pid)
969 {
970     string procName = UNKNOWN_PROCESS;
971     DumpCommonUtils::GetProcessNameByPid(pid, procName);
972     if (procName == UNKNOWN_PROCESS) {
973         string path = "/proc/" + to_string(pid) + "/status";
974         procName = FileUtils::GetInstance().GetProcValue(pid, path, "Name");
975     }
976     return procName;
977 }
978 
GetProcUid(const int32_t & pid)979 int32_t MemoryInfo::GetProcUid(const int32_t &pid)
980 {
981     string path = "/proc/" + to_string(pid) + "/status";
982     string procUid = FileUtils::GetInstance().GetProcValue(pid, path, "Uid");
983     if (procUid == UNKNOWN_PROCESS) {
984         DUMPER_HILOGE(MODULE_SERVICE, "GetProcUid failed");
985         return -1;
986     }
987     istringstream uid_stream(procUid);
988     string value;
989     uid_stream >> value;
990     int uid = -1;
991     if (!StrToInt(value, uid)) {
992         DUMPER_HILOGE(MODULE_COMMON, "StrToInt failed, value: %{public}s", value.c_str());
993         return -1;
994     }
995     return static_cast<int32_t>(uid);
996 }
997 
GetProcValue(const int32_t & pid,const string & key)998 uint64_t MemoryInfo::GetProcValue(const int32_t &pid, const string& key)
999 {
1000     string path = "/proc/" + to_string(pid) + "/status";
1001     std::string value = FileUtils::GetInstance().GetProcValue(pid, path, key);
1002     if (value == UNKNOWN_PROCESS) {
1003         DUMPER_HILOGE(MODULE_SERVICE, "GetProcStatusValue failed");
1004         return 0;
1005     }
1006     int number = 0;
1007     value = value.substr(0, value.size() - 3); // 3: ' kB'
1008     if (value.find_last_of(' ') != std::string::npos) {
1009         value = value.substr(value.find_last_of(' ') + 1);
1010     }
1011     if (!StrToInt(value, number)) {
1012         DUMPER_HILOGE(MODULE_COMMON, "StrToInt failed, value: %{public}s", value.c_str());
1013         return 0;
1014     }
1015     return static_cast<uint64_t>(number);
1016 }
1017 
1018 #ifdef HIDUMPER_MEMMGR_ENABLE
GetProcessAdjLabel(const int32_t pid)1019 string MemoryInfo::GetProcessAdjLabel(const int32_t pid)
1020 {
1021     string adjLabel = Memory::RECLAIM_PRIORITY_UNKNOWN_DESC;
1022     string fillPath = "/proc/" + to_string(pid) + "/oom_score_adj";
1023     if (!DumpUtils::PathIsValid(fillPath)) {
1024         DUMPER_HILOGE(MODULE_COMMON, "GetProcessAdjLabel leave|false, PathIsValid");
1025         return adjLabel;
1026     }
1027     auto fp = fopen(fillPath.c_str(), "rb");
1028     if (fp == nullptr) {
1029         DUMPER_HILOGE(MODULE_COMMON, "Open oom_score_adj failed.");
1030         return adjLabel;
1031     }
1032     constexpr int bufSize = 128; // 128: buf size
1033     char buf[bufSize] = {0};
1034     size_t readSum = fread(buf, 1, bufSize, fp);
1035     (void)fclose(fp);
1036     fp = nullptr;
1037     if (readSum < 1) {
1038         DUMPER_HILOGE(MODULE_COMMON, "Read oom_score_adj failed.");
1039         return adjLabel;
1040     }
1041     int value = Memory::RECLAIM_PRIORITY_UNKNOWN;
1042     std::string label(buf);
1043     if (label.empty()) {
1044         DUMPER_HILOGE(MODULE_COMMON, "label is empty.");
1045         return adjLabel;
1046     }
1047     if (!StrToInt(label.substr(0, label.size() - 1), value)) {
1048         DUMPER_HILOGE(MODULE_COMMON, "StrToInt failed.");
1049         return adjLabel;
1050     }
1051     adjLabel = Memory::GetReclaimPriorityString(value);
1052     return adjLabel;
1053 }
1054 #endif
1055 
GetScoreAdj(const int32_t pid)1056 int MemoryInfo::GetScoreAdj(const int32_t pid)
1057 {
1058     string filePath = "/proc/" + to_string(pid) + "/oom_score_adj";
1059     if (!DumpUtils::PathIsValid(filePath)) {
1060         DUMPER_HILOGE(MODULE_COMMON, "GetScoreAdj leave|false, PathIsValid");
1061         return -1;
1062     }
1063     std::string content = "-1";
1064     OHOS::LoadStringFromFile(filePath, content);
1065     int value = Memory::RECLAIM_PRIORITY_UNKNOWN;
1066     if (!StrToInt(content.substr(0, content.size() - 1), value)) {
1067         DUMPER_HILOGE(MODULE_COMMON, "GetScoreAdj|StrToInt failed.");
1068         return -1;
1069     }
1070     return value;
1071 }
1072 
GetPids()1073 bool MemoryInfo::GetPids()
1074 {
1075     bool success = DumpCommonUtils::GetUserPids(pids_);
1076     if (!success) {
1077         DUMPER_HILOGE(MODULE_SERVICE, "GetPids error");
1078     }
1079     return success;
1080 }
1081 
GetVss(const int32_t & pid)1082 uint64_t MemoryInfo::GetVss(const int32_t &pid)
1083 {
1084     string path = "/proc/" + to_string(pid) + "/statm";
1085     uint64_t res = 0;
1086     bool ret = FileUtils::GetInstance().LoadStringFromProcCb(path, true, true, [&](const string& line) -> void {
1087         if (!line.empty()) {
1088             uint64_t tempValue = 0;
1089             int retScanf = sscanf_s(line.c_str(), "%llu^*", &tempValue);
1090             if (retScanf != -1) {
1091                 res = tempValue * VSS_BIT;
1092             } else {
1093                 DUMPER_HILOGE(MODULE_SERVICE, "GetVss error! pid = %{public}d", pid);
1094             }
1095         }
1096     });
1097     if (!ret) {
1098         return 0;
1099     }
1100     return res;
1101 }
1102 
GetGraphicsMemory(int32_t pid,MemInfoData::GraphicsMemory & graphicsMemory,GraphicType graphicType)1103 bool MemoryInfo::GetGraphicsMemory(int32_t pid, MemInfoData::GraphicsMemory &graphicsMemory, GraphicType graphicType)
1104 {
1105     DUMPER_HILOGD(MODULE_SERVICE, "GetGraphicUsage start, pid:%{public}d", pid);
1106     std::shared_ptr<UCollectUtil::GraphicMemoryCollector> collector = UCollectUtil::GraphicMemoryCollector::Create();
1107     CollectResult<int32_t> data;
1108     data = collector->GetGraphicUsage(pid, graphicType, true);
1109     if (data.retCode != UCollect::UcError::SUCCESS) {
1110         DUMPER_HILOGE(MODULE_SERVICE, "collect progress GL or Graph error, ret:%{public}d", data.retCode);
1111         return false;
1112     }
1113     DUMPER_HILOGD(MODULE_SERVICE, "GetGraphicUsage end, pid:%{public}d", pid);
1114     if (graphicType == GraphicType::GL) {
1115         graphicsMemory.gl = static_cast<uint64_t>(data.data);
1116     } else if (graphicType == GraphicType::GRAPH) {
1117         graphicsMemory.graph = static_cast<uint64_t>(data.data);
1118     } else {
1119         DUMPER_HILOGE(MODULE_SERVICE, "graphic type is not support.");
1120         return false;
1121     }
1122     return true;
1123 }
1124 
GetMemByProcessPid(const int32_t & pid,MemInfoData::MemUsage & usage)1125 bool MemoryInfo::GetMemByProcessPid(const int32_t &pid, MemInfoData::MemUsage &usage)
1126 {
1127     bool success = false;
1128     MemInfoData::MemInfo memInfo;
1129     unique_ptr<ParseSmapsRollupInfo> getSmapsRollup = make_unique<ParseSmapsRollupInfo>();
1130     if (getSmapsRollup->GetMemInfo(pid, memInfo)) {
1131         if (!dumpPrune_) {
1132             usage.vss = GetVss(pid);
1133             usage.uss = memInfo.privateClean + memInfo.privateDirty;
1134             usage.rss = memInfo.rss;
1135         }
1136         usage.pss = memInfo.pss;
1137         usage.swapPss = memInfo.swapPss;
1138         usage.name = GetProcName(pid);
1139         usage.pid = pid;
1140 #ifdef HIDUMPER_MEMMGR_ENABLE
1141         usage.adjLabel = GetProcessAdjLabel(pid);
1142 #endif
1143         success = true;
1144     }
1145 
1146     MemInfoData::GraphicsMemory graphicsMemory;
1147     MemoryUtil::GetInstance().InitGraphicsMemory(graphicsMemory);
1148     if (GetGraphicsMemory(pid, graphicsMemory, GraphicType::GL)) {
1149         usage.gl = graphicsMemory.gl;
1150         if (!dumpPrune_) {
1151             usage.uss = usage.uss + graphicsMemory.gl;
1152             usage.rss = usage.rss + graphicsMemory.gl;
1153         }
1154         usage.pss = usage.pss + graphicsMemory.gl;
1155     }
1156     if (!dumpPrune_) {
1157         if (GetGraphicsMemory(pid, graphicsMemory, GraphicType::GRAPH)) {
1158             usage.graph = graphicsMemory.graph;
1159             usage.dma = graphicsMemory.graph;
1160             usage.uss = usage.uss + graphicsMemory.graph;
1161             usage.pss = usage.pss + graphicsMemory.graph;
1162             usage.rss = usage.rss + graphicsMemory.graph;
1163             DUMPER_HILOGD(MODULE_SERVICE, "uss:%{public}d pss:%{public}d rss:%{public}d gl:%{public}d graph:%{public}d",
1164                           static_cast<int>(usage.uss),
1165                           static_cast<int>(usage.pss),
1166                           static_cast<int>(usage.rss),
1167                           static_cast<int>(graphicsMemory.gl),
1168                           static_cast<int>(graphicsMemory.graph));
1169         }
1170     }
1171     return success;
1172 }
1173 
MemUsageToMatrix(const MemInfoData::MemUsage & memUsage,StringMatrix result)1174 void MemoryInfo::MemUsageToMatrix(const MemInfoData::MemUsage &memUsage, StringMatrix result)
1175 {
1176     string pid = to_string(memUsage.pid);
1177     StringUtils::GetInstance().SetWidth(PID_WIDTH_, BLANK_, true, pid);
1178 
1179     uint64_t pss = memUsage.pss + memUsage.swapPss;
1180     string totalPss = to_string(pss) + "(" + to_string(memUsage.swapPss) + " in SwapPss) kB";
1181     StringUtils::GetInstance().SetWidth(PSS_WIDTH_, BLANK_, false, totalPss);
1182 
1183     uint64_t gl = memUsage.gl;
1184     string unMappedGL = AddKbUnit(gl);
1185     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGL);
1186 
1187     string name = "    " + memUsage.name;
1188     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, name);
1189 
1190     if (!dumpPrune_) {
1191         uint64_t vss = memUsage.vss;
1192         string totalVss = AddKbUnit(vss);
1193         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalVss);
1194 
1195         uint64_t rss = memUsage.rss;
1196         string totalRss = AddKbUnit(rss);
1197         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalRss);
1198 
1199         uint64_t uss = memUsage.uss;
1200         string totalUss = AddKbUnit(uss);
1201         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalUss);
1202 
1203         uint64_t graph = memUsage.graph;
1204         string unMappedGraph = AddKbUnit(graph);
1205         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGraph);
1206 
1207         uint64_t dma = memUsage.dma;
1208         string unMappedDma = AddKbUnit(dma);
1209         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedDma);
1210 
1211         uint64_t purgSum = memUsage.purgSum;
1212         string unMappedPurgSum = AddKbUnit(purgSum);
1213         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgSum);
1214 
1215         uint64_t purgPin = memUsage.purgPin;
1216         string unMappedPurgPin = AddKbUnit(purgPin);
1217         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgPin);
1218 
1219         (void)dprintf(rawParamFd_, "%s %s %s %s %s %s %s %s %s %s %s\n", pid.c_str(),
1220             totalPss.c_str(), totalVss.c_str(), totalRss.c_str(), totalUss.c_str(),
1221             unMappedGL.c_str(), unMappedGraph.c_str(), unMappedDma.c_str(), unMappedPurgSum.c_str(),
1222             unMappedPurgPin.c_str(), name.c_str());
1223     } else {
1224         int scoreAdj = GetScoreAdj(memUsage.pid);
1225         string scoreAdjStr = to_string(scoreAdj);
1226         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, scoreAdjStr);
1227 
1228         (void)dprintf(rawParamFd_, "%s %s %s %s %s\n", pid.c_str(),
1229             totalPss.c_str(), unMappedGL.c_str(), scoreAdjStr.c_str(), name.c_str());
1230     }
1231 }
1232 
AddMemByProcessTitle(StringMatrix result,string sortType)1233 void MemoryInfo::AddMemByProcessTitle(StringMatrix result, string sortType)
1234 {
1235     string processTitle = "Total Memory Usage by " + sortType + ":";
1236     (void)dprintf(rawParamFd_, "%s\n", processTitle.c_str());
1237 
1238     string pid = "PID";
1239     StringUtils::GetInstance().SetWidth(PID_WIDTH_, BLANK_, true, pid);
1240 
1241     string totalPss = "Total Pss(xxx in SwapPss)";
1242     StringUtils::GetInstance().SetWidth(PSS_WIDTH_, BLANK_, false, totalPss);
1243 
1244     string unMappedGL = MemoryFilter::GetInstance().GL_OUT_LABEL;
1245     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGL);
1246 
1247     string name = "    Name";
1248     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, name);
1249 
1250     if (!dumpPrune_) {
1251         string totalVss = "Total Vss";
1252         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalVss);
1253 
1254         string totalRss = "Total Rss";
1255         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalRss);
1256 
1257         string totalUss = "Total Uss";
1258         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalUss);
1259 
1260         string unMappedGraph = MemoryFilter::GetInstance().GRAPH_OUT_LABEL;
1261         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGraph);
1262 
1263         string unMappedDma = MemoryFilter::GetInstance().DMA_OUT_LABEL;
1264         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedDma);
1265 
1266         string unMappedPurgSum = MemoryFilter::GetInstance().PURGSUM_OUT_LABEL;
1267         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgSum);
1268 
1269         string unMappedPurgPin = MemoryFilter::GetInstance().PURGPIN_OUT_LABEL;
1270         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgPin);
1271 
1272         (void)dprintf(rawParamFd_, "%s %s %s %s %s %s %s %s %s %s %s\n", pid.c_str(),
1273             totalPss.c_str(), totalVss.c_str(), totalRss.c_str(), totalUss.c_str(),
1274             unMappedGL.c_str(), unMappedGraph.c_str(), unMappedDma.c_str(), unMappedPurgSum.c_str(),
1275             unMappedPurgPin.c_str(), name.c_str());
1276     } else {
1277         string adjLabel = "AdjLabel";
1278         StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, adjLabel);
1279 
1280         (void)dprintf(rawParamFd_, "%s %s %s %s %s\n", pid.c_str(),
1281             totalPss.c_str(), unMappedGL.c_str(), adjLabel.c_str(), name.c_str());
1282     }
1283 }
1284 
GetMemoryInfoInit(StringMatrix result)1285 bool MemoryInfo::GetMemoryInfoInit(StringMatrix result)
1286 {
1287     if (!isReady_) {
1288         memUsages_.clear();
1289         pids_.clear();
1290         totalGL_ = 0;
1291         totalGraph_ = 0;
1292         AddMemByProcessTitle(result, "PID");
1293         if (!GetPids()) {
1294             DUMPER_HILOGE(MODULE_SERVICE, "GetPids error!\n");
1295             return false;
1296         }
1297         isReady_ = true;
1298     }
1299     return true;
1300 }
1301 
GetMemoryUsageInfo(StringMatrix result)1302 void MemoryInfo::GetMemoryUsageInfo(StringMatrix result)
1303 {
1304     MemInfoData::MemUsage usage;
1305     MemoryUtil::GetInstance().InitMemUsage(usage);
1306     for (auto pid : pids_) {
1307         if (GetMemByProcessPid(pid, usage)) {
1308             memUsages_.push_back(usage);
1309             adjMemResult_[usage.adjLabel].push_back(usage);
1310             totalGL_ += usage.gl;
1311             totalGraph_ += usage.graph;
1312             totalDma_ += usage.dma;
1313             MemUsageToMatrix(usage, result);
1314         } else {
1315             DUMPER_HILOGE(MODULE_SERVICE, "Get smaps_rollup error! pid = %{public}d\n", static_cast<int>(pid));
1316         }
1317     }
1318 }
1319 
GetMemoryInfoNoPid(int fd,StringMatrix result)1320 DumpStatus MemoryInfo::GetMemoryInfoNoPid(int fd, StringMatrix result)
1321 {
1322     std::lock_guard<std::mutex> lock(mutex_);
1323     rawParamFd_ = fd;
1324     (void)dprintf(rawParamFd_, "%s\n", MEMORY_LINE.c_str());
1325     if (!GetMemoryInfoInit(result)) {
1326         return DUMP_FAIL;
1327     }
1328 
1329     if (!dumpSmapsOnStart_) {
1330         dumpSmapsOnStart_ = true;
1331         std::promise<GroupMap> promise;
1332         fut_ = promise.get_future();
1333         std::thread([promise = std::move(promise), this]() mutable {
1334             GroupMap groupMap;
1335             std::vector<int32_t> pids(this->pids_);
1336             for (auto pid : pids) {
1337                 GetSmapsInfoNoPid(pid, groupMap);
1338             }
1339             promise.set_value(groupMap);
1340             }).detach();
1341     }
1342     GetMemoryUsageInfo(result);
1343     return DealResult(result);
1344 }
1345 
GetMemoryInfoPrune(int fd,StringMatrix result)1346 DumpStatus MemoryInfo::GetMemoryInfoPrune(int fd, StringMatrix result)
1347 {
1348     std::lock_guard<std::mutex> lock(mutex_);
1349     rawParamFd_ = fd;
1350     dumpPrune_ = true;
1351     (void)dprintf(rawParamFd_, "%s\n", MEMORY_LINE.c_str());
1352     if (!GetMemoryInfoInit(result)) {
1353         return DUMP_FAIL;
1354     }
1355     GetMemoryUsageInfo(result);
1356     return DUMP_OK;
1357 }
1358 
DealResult(StringMatrix result)1359 DumpStatus MemoryInfo::DealResult(StringMatrix result)
1360 {
1361     ValueMap meminfoResult;
1362     if (!GetMeminfo(meminfoResult)) {
1363         DUMPER_HILOGE(MODULE_SERVICE, "Get meminfo error\n");
1364         return DUMP_FAIL;
1365     }
1366 
1367     GetSortedMemoryInfoNoPid(result);
1368     SaveStringToFd(rawParamFd_, "\n");
1369 #ifdef HIDUMPER_MEMMGR_ENABLE
1370     GetMemoryByAdj(result);
1371 #endif
1372     SaveStringToFd(rawParamFd_, "\n");
1373 
1374     GroupMap smapsResult = fut_.get();
1375 
1376     GetPssTotal(smapsResult, result);
1377     SaveStringToFd(rawParamFd_, "\n");
1378 
1379     GetRamUsage(smapsResult, meminfoResult, result);
1380     SaveStringToFd(rawParamFd_, "\n");
1381 
1382     GetRamCategory(smapsResult, meminfoResult, result);
1383     SaveStringToFd(rawParamFd_, "\n");
1384 
1385     GetPurgTotal(meminfoResult, result);
1386 
1387     isReady_ = false;
1388     dumpSmapsOnStart_ = false;
1389     memUsages_.clear();
1390     smapsResult.clear();
1391     return DUMP_OK;
1392 }
1393 
GetSortedMemoryInfoNoPid(StringMatrix result)1394 void MemoryInfo::GetSortedMemoryInfoNoPid(StringMatrix result)
1395 {
1396     SaveStringToFd(rawParamFd_, "\n");
1397     AddMemByProcessTitle(result, "Size");
1398 
1399     std::sort(memUsages_.begin(), memUsages_.end(),
1400         [] (MemInfoData::MemUsage &left, MemInfoData::MemUsage &right) {
1401         if (right.pss + right.swapPss != left.pss + left.swapPss) {
1402             return right.pss + right.swapPss < left.pss + left.swapPss;
1403         }
1404         if (right.vss != left.vss) {
1405             return right.vss < left.vss;
1406         }
1407         if (right.rss != left.rss) {
1408             return right.rss < left.rss;
1409         }
1410         if (right.uss != left.uss) {
1411             return right.uss < left.uss;
1412         }
1413         return right.pid < left.pid;
1414     });
1415 
1416     for (auto &memUsage : memUsages_) {
1417         MemUsageToMatrix(memUsage, result);
1418     }
1419 }
1420 
1421 #ifdef HIDUMPER_MEMMGR_ENABLE
GetMemoryByAdj(StringMatrix result)1422 void MemoryInfo::GetMemoryByAdj(StringMatrix result)
1423 {
1424     SaveStringToFd(rawParamFd_, "Total Pss by OOM adjustment:\n");
1425 
1426     vector<string> reclaimPriority_;
1427     for (auto reclaim : Memory::ReclaimPriorityMapping) {
1428         reclaimPriority_.push_back(reclaim.second);
1429     }
1430     reclaimPriority_.push_back(Memory::RECLAIM_PRIORITY_UNKNOWN_DESC);
1431 
1432     for (const auto &adjLabel : reclaimPriority_) {
1433         vector<MemInfoData::MemUsage> memUsages = adjMemResult_[adjLabel];
1434         vector<string> label;
1435         if (memUsages.size() == 0) {
1436             SaveStringToFd(rawParamFd_, adjLabel + ": " + AddKbUnit(0) + "\n");
1437             continue;
1438         }
1439         uint64_t totalPss = accumulate(memUsages.begin(), memUsages.end(), (uint64_t)0,
1440         [] (uint64_t a, MemInfoData::MemUsage &b) {
1441             return a + b.pss + b.swapPss;
1442         });
1443         SaveStringToFd(rawParamFd_, adjLabel + ": " + AddKbUnit(totalPss) + "\n");
1444 
1445         std::sort(memUsages.begin(), memUsages.end(),
1446             [] (MemInfoData::MemUsage &left, MemInfoData::MemUsage &right) {
1447             return right.pss + right.swapPss < left.pss + left.swapPss;
1448         });
1449         for (const auto &memUsage : memUsages) {
1450             string name = PRE_BLANK + memUsage.name + "(pid=" + to_string(memUsage.pid) + "): ";
1451             StringUtils::GetInstance().SetWidth(NAME_AND_PID_WIDTH, BLANK_, true, name);
1452             name += AddKbUnit(memUsage.pss + memUsage.swapPss);
1453             if (memUsage.swapPss > 0) {
1454                 name += " (" + to_string(memUsage.swapPss) + " kB in SwapPss)";
1455             }
1456             SaveStringToFd(rawParamFd_, name + "\n");
1457         }
1458     }
1459 }
1460 #endif
1461 
SetPss(MemInfoData::MemInfo & meminfo,uint64_t value)1462 void MemoryInfo::SetPss(MemInfoData::MemInfo &meminfo, uint64_t value)
1463 {
1464     meminfo.pss += value;
1465 }
1466 
SetSharedClean(MemInfoData::MemInfo & meminfo,uint64_t value)1467 void MemoryInfo::SetSharedClean(MemInfoData::MemInfo &meminfo, uint64_t value)
1468 {
1469     meminfo.sharedClean += value;
1470 }
1471 
SetSharedDirty(MemInfoData::MemInfo & meminfo,uint64_t value)1472 void MemoryInfo::SetSharedDirty(MemInfoData::MemInfo &meminfo, uint64_t value)
1473 {
1474     meminfo.sharedDirty += value;
1475 }
1476 
SetPrivateClean(MemInfoData::MemInfo & meminfo,uint64_t value)1477 void MemoryInfo::SetPrivateClean(MemInfoData::MemInfo &meminfo, uint64_t value)
1478 {
1479     meminfo.privateClean += value;
1480 }
1481 
SetPrivateDirty(MemInfoData::MemInfo & meminfo,uint64_t value)1482 void MemoryInfo::SetPrivateDirty(MemInfoData::MemInfo &meminfo, uint64_t value)
1483 {
1484     meminfo.privateDirty += value;
1485 }
1486 
SetSwap(MemInfoData::MemInfo & meminfo,uint64_t value)1487 void MemoryInfo::SetSwap(MemInfoData::MemInfo &meminfo, uint64_t value)
1488 {
1489     meminfo.swap += value;
1490 }
1491 
SetSwapPss(MemInfoData::MemInfo & meminfo,uint64_t value)1492 void MemoryInfo::SetSwapPss(MemInfoData::MemInfo &meminfo, uint64_t value)
1493 {
1494     meminfo.swapPss += value;
1495 }
SetHeapSize(MemInfoData::MemInfo & meminfo,uint64_t value)1496 void MemoryInfo::SetHeapSize(MemInfoData::MemInfo &meminfo, uint64_t value)
1497 {
1498     meminfo.heapSize += value;
1499 }
1500 
SetHeapAlloc(MemInfoData::MemInfo & meminfo,uint64_t value)1501 void MemoryInfo::SetHeapAlloc(MemInfoData::MemInfo &meminfo, uint64_t value)
1502 {
1503     meminfo.heapAlloc += value;
1504 }
1505 
SetHeapFree(MemInfoData::MemInfo & meminfo,uint64_t value)1506 void MemoryInfo::SetHeapFree(MemInfoData::MemInfo &meminfo, uint64_t value)
1507 {
1508     meminfo.heapFree += value;
1509 }
1510 } // namespace HiviewDFX
1511 } // namespace OHOS