• 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 
17 #include <dlfcn.h>
18 #include <cinttypes>
19 #include <fstream>
20 #include <numeric>
21 #include <thread>
22 #include <v1_0/imemory_tracker_interface.h>
23 
24 #include "dump_common_utils.h"
25 #include "dump_utils.h"
26 #include "executor/memory/get_cma_info.h"
27 #include "executor/memory/get_heap_info.h"
28 #include "executor/memory/get_hardware_info.h"
29 #include "executor/memory/get_kernel_info.h"
30 #include "executor/memory/get_process_info.h"
31 #include "executor/memory/get_ram_info.h"
32 #include "executor/memory/memory_util.h"
33 #include "executor/memory/parse/meminfo_data.h"
34 #include "executor/memory/parse/parse_meminfo.h"
35 #include "executor/memory/parse/parse_smaps_rollup_info.h"
36 #include "executor/memory/parse/parse_smaps_info.h"
37 #include "file_ex.h"
38 #include "hdf_base.h"
39 #include "hilog_wrapper.h"
40 #include "securec.h"
41 #include "string_ex.h"
42 #include "util/string_utils.h"
43 #include "util/file_utils.h"
44 #ifdef HIDUMPER_GRAPHIC_ENABLE
45 using namespace OHOS::Rosen;
46 #endif
47 
48 using namespace std;
49 using namespace OHOS::HDI::Memorytracker::V1_0;
50 
51 namespace OHOS {
52 namespace HiviewDFX {
53 static uint64_t g_sumPidsMemGL = 0;
54 static const std::string LIB = "libai_mnt_client.so";
55 
56 static const std::string UNKNOWN_PROCESS = "unknown";
57 static const std::string PRE_BLANK = "   ";
58 static const std::string MEMORY_LINE = "-------------------------------[memory]-------------------------------";
59 constexpr int HIAI_MAX_QUERIED_USER_MEMINFO_LIMIT = 256;
60 constexpr char HIAI_MEM_INFO_FN[] = "HIAI_Memory_QueryAllUserAllocatedMemInfo";
61 constexpr int PAGETAG_MIN_LEN = 2;
62 using HiaiFunc = int (*)(MemInfoData::HiaiUserAllocatedMemInfo*, int, int*);
63 
MemoryInfo()64 MemoryInfo::MemoryInfo()
65 {
66     methodVec_.clear();
67     methodVec_.push_back(make_pair(MEMINFO_PSS,
68         bind(&MemoryInfo::SetPss, this, placeholders::_1, placeholders::_2)));
69     methodVec_.push_back(make_pair(MEMINFO_SHARED_CLEAN,
70         bind(&MemoryInfo::SetSharedClean, this, placeholders::_1, placeholders::_2)));
71     methodVec_.push_back(make_pair(MEMINFO_SHARED_DIRTY,
72         bind(&MemoryInfo::SetSharedDirty, this, placeholders::_1, placeholders::_2)));
73     methodVec_.push_back(make_pair(MEMINFO_PRIVATE_CLEAN,
74         bind(&MemoryInfo::SetPrivateClean, this, placeholders::_1, placeholders::_2)));
75     methodVec_.push_back(make_pair(MEMINFO_PRIVATE_DIRTY,
76         bind(&MemoryInfo::SetPrivateDirty, this, placeholders::_1, placeholders::_2)));
77     methodVec_.push_back(make_pair(MEMINFO_SWAP,
78         bind(&MemoryInfo::SetSwap, this, placeholders::_1, placeholders::_2)));
79     methodVec_.push_back(make_pair(MEMINFO_SWAP_PSS,
80         bind(&MemoryInfo::SetSwapPss, this, placeholders::_1, placeholders::_2)));
81     methodVec_.push_back(make_pair(MEMINFO_HEAP_SIZE,
82         bind(&MemoryInfo::SetHeapSize, this, placeholders::_1, placeholders::_2)));
83     methodVec_.push_back(make_pair(MEMINFO_HEAP_ALLOC,
84         bind(&MemoryInfo::SetHeapAlloc, this, placeholders::_1, placeholders::_2)));
85     methodVec_.push_back(make_pair(MEMINFO_HEAP_FREE,
86         bind(&MemoryInfo::SetHeapFree, this, placeholders::_1, placeholders::_2)));
87 }
88 
~MemoryInfo()89 MemoryInfo::~MemoryInfo()
90 {
91 }
92 
insertMemoryTitle(StringMatrix result)93 void MemoryInfo::insertMemoryTitle(StringMatrix result)
94 {
95     // Pss        Shared   ---- this line is line1
96     // Total      Clean    ---- this line is line2
97     // (KB)         (KB)    ---- this line is line3
98     // -----      ------   ---- this line is line4
99 
100     vector<string> line1;
101     vector<string> line2;
102     vector<string> line3;
103     vector<string> line4;
104 
105     string space = " ";
106     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, space);
107 
108     string separator = "-";
109     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, SEPARATOR_, false, separator);
110 
111     string unit = "(" + MemoryUtil::GetInstance().KB_UNIT_ + " )";
112     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, unit);
113 
114     // Add  spaces at the beginning of the line
115     line1.push_back(space);
116     line2.push_back(space);
117     line3.push_back(space);
118     line4.push_back(space);
119 
120     for (string str : MemoryFilter::GetInstance().TITLE_HAS_PID_) {
121         vector<string> types;
122         StringUtils::GetInstance().StringSplit(str, "_", types);
123         if (types.size() == TYPE_SIZE) {
124             string title1 = types.at(0);
125             StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, title1);
126             line1.push_back(title1);
127 
128             string title2 = types.at(1);
129             StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, title2);
130             line2.push_back(title2);
131             line3.push_back(unit);
132             line4.push_back(separator);
133         }
134     }
135     result->push_back(line1);
136     result->push_back(line2);
137     result->push_back(line3);
138     result->push_back(line4);
139 }
140 
BuildResult(const GroupMap & infos,StringMatrix result)141 void MemoryInfo::BuildResult(const GroupMap &infos, StringMatrix result)
142 {
143     insertMemoryTitle(result);
144     for (const auto &info : infos) {
145         vector<string> tempResult;
146         vector<string> pageTag;
147         StringUtils::GetInstance().StringSplit(info.first, "#", pageTag);
148         string group;
149         if (pageTag.size() < PAGETAG_MIN_LEN) {
150             DUMPER_HILOGE(MODULE_COMMON, "Infos are invalid, info.first: %s", info.first.c_str());
151             return;
152         }
153         if (pageTag[1] == "other") {
154             group = pageTag[0] == MemoryFilter::GetInstance().FILE_PAGE_TAG ? "FilePage other" : "AnonPage other";
155         } else {
156             group = pageTag[1];
157         }
158         StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, group);
159         tempResult.push_back(group);
160 
161         auto &valueMap = info.second;
162         for (const auto &tag : MemoryFilter::GetInstance().VALUE_WITH_PID) {
163             auto it = valueMap.find(tag);
164             string value = "0";
165             if (it != valueMap.end()) {
166                 value = to_string(it->second);
167             }
168             StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, value);
169             tempResult.push_back(value);
170         }
171         result->push_back(tempResult);
172     }
173 }
174 
175 
CalcGroup(const GroupMap & infos,StringMatrix result)176 void MemoryInfo::CalcGroup(const GroupMap &infos, StringMatrix result)
177 {
178     MemInfoData::MemInfo meminfo;
179     MemoryUtil::GetInstance().InitMemInfo(meminfo);
180     for (const auto &info : infos) {
181         auto &valueMap = info.second;
182         for (const auto &method : methodVec_) {
183             auto it = valueMap.find(method.first);
184             if (it != valueMap.end()) {
185                 method.second(meminfo, it->second);
186             }
187         }
188     }
189 
190     vector<string> lines;
191     vector<string> values;
192 
193     MemoryUtil::GetInstance().SetMemTotalValue("Total", lines, values);
194     MemoryUtil::GetInstance().SetMemTotalValue(to_string(meminfo.pss + meminfo.swapPss), lines, values);
195     MemoryUtil::GetInstance().SetMemTotalValue(to_string(meminfo.sharedClean), lines, values);
196     MemoryUtil::GetInstance().SetMemTotalValue(to_string(meminfo.sharedDirty), lines, values);
197     MemoryUtil::GetInstance().SetMemTotalValue(to_string(meminfo.privateClean), lines, values);
198     MemoryUtil::GetInstance().SetMemTotalValue(to_string(meminfo.privateDirty), lines, values);
199     MemoryUtil::GetInstance().SetMemTotalValue(to_string(meminfo.swap), lines, values);
200     MemoryUtil::GetInstance().SetMemTotalValue(to_string(meminfo.swapPss), lines, values);
201     MemoryUtil::GetInstance().SetMemTotalValue(to_string(meminfo.heapSize), lines, values);
202     MemoryUtil::GetInstance().SetMemTotalValue(to_string(meminfo.heapAlloc), lines, values);
203     MemoryUtil::GetInstance().SetMemTotalValue(to_string(meminfo.heapFree), lines, values);
204 
205     result->push_back(lines);
206     result->push_back(values);
207 }
208 
GetRenderServiceGraphics(int32_t pid,MemInfoData::GraphicsMemory & graphicsMemory)209 bool MemoryInfo::GetRenderServiceGraphics(int32_t pid, MemInfoData::GraphicsMemory &graphicsMemory)
210 {
211     bool ret = false;
212     sptr<IMemoryTrackerInterface> memtrack = IMemoryTrackerInterface::Get(true);
213     if (memtrack == nullptr) {
214         DUMPER_HILOGE(MODULE_SERVICE, "memtrack service is null");
215         return ret;
216     }
217 
218     std::vector<MemoryRecord> records;
219     if (memtrack->GetDevMem(pid, MEMORY_TRACKER_TYPE_GL, records) == HDF_SUCCESS) {
220         uint64_t value = 0;
221         for (const auto& record : records) {
222             if ((static_cast<uint32_t>(record.flags) & FLAG_UNMAPPED) == FLAG_UNMAPPED) {
223                 value = static_cast<uint64_t>(record.size / BYTE_PER_KB);
224                 break;
225             }
226         }
227         graphicsMemory.gl = value;
228         ret = true;
229     }
230     return ret;
231 }
232 
IsRenderService(int32_t pid)233 bool MemoryInfo::IsRenderService(int32_t pid)
234 {
235     std::string rsName = "render_service";
236     std::string processName = GetProcName(pid);
237     const char whitespace[] = " \n\t\v\r\f";
238     processName.erase(0, processName.find_first_not_of(whitespace));
239     processName.erase(processName.find_last_not_of(whitespace) + 1U);
240     if (processName == rsName) {
241         return true;
242     }
243     return false;
244 }
245 
GetMemoryInfoByPid(const int32_t & pid,StringMatrix result)246 bool MemoryInfo::GetMemoryInfoByPid(const int32_t &pid, StringMatrix result)
247 {
248     std::lock_guard<std::mutex> lock(mutex_);
249     if (!dmaInfo_.ParseDmaInfo()) {
250         DUMPER_HILOGE(MODULE_SERVICE, "Parse dma info error\n");
251     }
252     GroupMap groupMap;
253     GroupMap nativeGroupMap;
254     unique_ptr<ParseSmapsInfo> parseSmapsInfo = make_unique<ParseSmapsInfo>();
255     if (!parseSmapsInfo->GetInfo(MemoryFilter::APPOINT_PID, pid, nativeGroupMap, groupMap)) {
256         DUMPER_HILOGE(MODULE_SERVICE, "parse smaps info fail, pid:%{public}d", pid);
257         return false;
258     }
259 
260     unique_ptr<GetHeapInfo> getHeapInfo = make_unique<GetHeapInfo>();
261     if (!getHeapInfo->GetInfo(MemoryFilter::APPOINT_PID, pid, groupMap)) {
262         DUMPER_HILOGE(MODULE_SERVICE, "get heap info fail");
263         return false;
264     }
265 
266     MemInfoData::GraphicsMemory graphicsMemory;
267     MemoryUtil::GetInstance().InitGraphicsMemory(graphicsMemory);
268     graphicsMemory.graph = dmaInfo_.GetDmaByPid(pid);
269     GetGraphicsMemory(pid, graphicsMemory);
270     SetGraphGroupMap(groupMap, graphicsMemory);
271     BuildResult(groupMap, result);
272     CalcGroup(groupMap, result);
273     GetNativeHeap(nativeGroupMap, result);
274     GetPurgByPid(pid, result);
275     GetDmaByPid(pid, result);
276     GetHiaiServerIon(pid, result);
277     return true;
278 }
279 
SetGraphGroupMap(GroupMap & groupMap,MemInfoData::GraphicsMemory & graphicsMemory)280 void MemoryInfo::SetGraphGroupMap(GroupMap& groupMap, MemInfoData::GraphicsMemory &graphicsMemory)
281 {
282     map<string, uint64_t> valueMap;
283     valueMap.insert(pair<string, uint64_t>("Pss", graphicsMemory.gl));
284     valueMap.insert(pair<string, uint64_t>("Private_Dirty", graphicsMemory.gl));
285     groupMap.insert(pair<string, map<string, uint64_t>>("AnonPage # GL", valueMap));
286     valueMap.clear();
287     valueMap.insert(pair<string, uint64_t>("Pss", graphicsMemory.graph));
288     valueMap.insert(pair<string, uint64_t>("Private_Dirty", graphicsMemory.graph));
289     groupMap.insert(pair<string, map<string, uint64_t>>("AnonPage # Graph", valueMap));
290 }
291 
AddKbUnit(const uint64_t & value) const292 string MemoryInfo::AddKbUnit(const uint64_t &value) const
293 {
294     return to_string(value) + MemoryUtil::GetInstance().KB_UNIT_;
295 }
296 
GetSmapsInfoNoPid(const int32_t & pid,GroupMap & result)297 bool MemoryInfo::GetSmapsInfoNoPid(const int32_t &pid, GroupMap &result)
298 {
299     GroupMap NativeMap;
300     unique_ptr<ParseSmapsInfo> parseSmapsInfo = make_unique<ParseSmapsInfo>();
301     return parseSmapsInfo->GetInfo(MemoryFilter::NOT_SPECIFIED_PID, pid, NativeMap, result);
302 }
303 
GetMeminfo(ValueMap & result)304 bool MemoryInfo::GetMeminfo(ValueMap &result)
305 {
306     unique_ptr<ParseMeminfo> parseMeminfo = make_unique<ParseMeminfo>();
307     return parseMeminfo->GetMeminfo(result);
308 }
309 
GetHardWareUsage(StringMatrix result)310 bool MemoryInfo::GetHardWareUsage(StringMatrix result)
311 {
312     uint64_t value;
313     unique_ptr<GetHardwareInfo> getHardwareInfo = make_unique<GetHardwareInfo>();
314     if (getHardwareInfo->GetHardwareUsage(value)) {
315         string title = "Hardware Usage:";
316         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
317         SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
318         return true;
319     }
320     return false;
321 }
322 
GetCMAUsage(StringMatrix result)323 bool MemoryInfo::GetCMAUsage(StringMatrix result)
324 {
325     uint64_t value = 0;
326     unique_ptr<GetCMAInfo> getCMAInfo = make_unique<GetCMAInfo>();
327     bool success = getCMAInfo->GetUsed(value);
328     if (success) {
329         string title = "CMA Usage:";
330         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
331         SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
332     }
333     return success;
334 }
335 
GetKernelUsage(const ValueMap & infos,StringMatrix result)336 bool MemoryInfo::GetKernelUsage(const ValueMap &infos, StringMatrix result)
337 {
338     uint64_t value = 0;
339     unique_ptr<GetKernelInfo> getGetKernelInfo = make_unique<GetKernelInfo>();
340     bool success = getGetKernelInfo->GetKernel(infos, value);
341     if (success) {
342         string title = "Kernel Usage:";
343         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
344         SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
345     }
346     return success;
347 }
348 
GetProcesses(const GroupMap & infos,StringMatrix result)349 void MemoryInfo::GetProcesses(const GroupMap &infos, StringMatrix result)
350 {
351     uint64_t value = 0;
352 
353     unique_ptr<GetProcessInfo> getProcessInfo = make_unique<GetProcessInfo>();
354     value = getProcessInfo->GetProcess(infos);
355 
356     string title = "Processes Usage:";
357     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
358     SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
359 }
360 
GetPssTotal(const GroupMap & infos,StringMatrix result)361 void MemoryInfo::GetPssTotal(const GroupMap &infos, StringMatrix result)
362 {
363     SaveStringToFd(rawParamFd_, "Total Pss by Category:\n");
364     vector<pair<string, uint64_t>> filePage;
365     vector<pair<string, uint64_t>> anonPage;
366     for (const auto &info : infos) {
367         vector<string> pageTag;
368         StringUtils::GetInstance().StringSplit(info.first, "#", pageTag);
369         string group = pageTag[1];
370         auto &valueMap = info.second;
371         uint64_t pssValue = 0;
372         for (const auto &str : MemoryFilter::GetInstance().CALC_PSS_TOTAL_) {
373             auto it = valueMap.find(str);
374             if (it != valueMap.end()) {
375                 pssValue += it->second;
376             }
377         }
378 
379         if (pageTag[0] == MemoryFilter::GetInstance().FILE_PAGE_TAG) {
380             filePage.push_back(make_pair(group, pssValue));
381         } else {
382             anonPage.push_back(make_pair(group, pssValue));
383         }
384     }
385     PairToStringMatrix(MemoryFilter::GetInstance().FILE_PAGE_TAG, filePage, result);
386     PairToStringMatrix(MemoryFilter::GetInstance().ANON_PAGE_TAG, anonPage, result);
387 
388     vector<pair<string, uint64_t>> gpuValue;
389     gpuValue.push_back(make_pair(MemoryFilter::GetInstance().GL_OUT_LABEL, totalGL_));
390     PairToStringMatrix(MemoryFilter::GetInstance().GPU_TAG, gpuValue, result);
391 
392     vector<pair<string, uint64_t>> graphValue;
393     graphValue.push_back(make_pair(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, totalGraph_));
394     PairToStringMatrix(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, graphValue, result);
395 
396     vector<pair<string, uint64_t>> dmaValue;
397     dmaValue.push_back(make_pair(MemoryFilter::GetInstance().DMA_OUT_LABEL, dmaInfo_.GetTotalDma()));
398     PairToStringMatrix(MemoryFilter::GetInstance().DMA_TAG, dmaValue, result);
399 }
400 
PairToStringMatrix(const string & titleStr,vector<pair<string,uint64_t>> & vec,StringMatrix result)401 void MemoryInfo::PairToStringMatrix(const string &titleStr, vector<pair<string, uint64_t>> &vec, StringMatrix result)
402 {
403     uint64_t totalPss = accumulate(vec.begin(), vec.end(), (uint64_t)0, [] (uint64_t a, pair<string, uint64_t> &b) {
404         return a + b.second;
405     });
406     SaveStringToFd(rawParamFd_, titleStr + "(" + AddKbUnit(totalPss) + "):\n");
407 
408     std::sort(vec.begin(), vec.end(),
409         [] (pair<string, uint64_t> &left, pair<string, uint64_t> &right) {
410         return right.second < left.second;
411     });
412     for (const auto &pair : vec) {
413         string pssStr = AddKbUnit(pair.second);
414         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, pssStr);
415         SaveStringToFd(rawParamFd_, pssStr + " : " + pair.first + "\n");
416     }
417 }
418 
GetRamUsage(const GroupMap & smapsinfos,const ValueMap & meminfo,StringMatrix result)419 void MemoryInfo::GetRamUsage(const GroupMap &smapsinfos, const ValueMap &meminfo, StringMatrix result)
420 {
421     unique_ptr<GetRamInfo> getRamInfo = make_unique<GetRamInfo>();
422     GetRamInfo::Ram ram = getRamInfo->GetRam(smapsinfos, meminfo);
423 
424     string totalTitle = "Total RAM:";
425     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalTitle);
426     SaveStringToFd(rawParamFd_, totalTitle + AddKbUnit(ram.total) + "\n");
427 
428     string freeTitle = "Free RAM:";
429     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, freeTitle);
430     SaveStringToFd(rawParamFd_, freeTitle + AddKbUnit(ram.free) +
431         " (" + to_string(ram.cachedInfo) + " cached + " + to_string(ram.freeInfo) + " free)\n");
432 
433     string usedTitle = "Used RAM:";
434     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, usedTitle);
435     SaveStringToFd(rawParamFd_, usedTitle + AddKbUnit(ram.used) +
436         " (" + to_string(ram.totalPss) + " total pss + " + to_string(ram.kernelUsed) + " kernel)\n");
437 
438     string lostTitle = "Lost RAM:";
439     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, lostTitle);
440     SaveStringToFd(rawParamFd_, lostTitle + to_string(ram.lost) + MemoryUtil::GetInstance().KB_UNIT_ + "\n");
441 }
442 
GetPurgTotal(const ValueMap & meminfo,StringMatrix result)443 void MemoryInfo::GetPurgTotal(const ValueMap &meminfo, StringMatrix result)
444 {
445     SaveStringToFd(rawParamFd_, "Total Purgeable:\n");
446 
447     uint64_t purgSumTotal = 0;
448     uint64_t purgPinTotal = 0;
449     auto purgSumActive = meminfo.find(MemoryFilter::GetInstance().PURG_SUM[0]);
450     auto purgSumInactive = meminfo.find(MemoryFilter::GetInstance().PURG_SUM[1]);
451     auto purgPinPined = meminfo.find(MemoryFilter::GetInstance().PURG_PIN[0]);
452     if (purgSumActive == meminfo.end() || purgSumInactive == meminfo.end() || purgPinPined == meminfo.end()) {
453         DUMPER_HILOGE(MODULE_SERVICE, "fail to get purg info \n");
454     } else {
455         purgSumTotal = purgSumActive->second + purgSumInactive->second;
456         purgPinTotal = purgPinPined->second;
457     }
458 
459     string totalPurgSumTitle = "Total PurgSum:";
460     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalPurgSumTitle);
461     SaveStringToFd(rawParamFd_, totalPurgSumTitle + AddKbUnit(purgSumTotal) + "\n");
462 
463     string totalPurgPinTitle = "Total PurgPin:";
464     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalPurgPinTitle);
465     SaveStringToFd(rawParamFd_, totalPurgPinTitle + AddKbUnit(purgPinTotal) + "\n");
466 }
467 
GetPurgByPid(const int32_t & pid,StringMatrix result)468 void MemoryInfo::GetPurgByPid(const int32_t &pid, StringMatrix result)
469 {
470     AddBlankLine(result);
471     vector<string> title;
472     title.push_back("Purgeable:");
473     result->push_back(title);
474 
475     vector<string> purgSum;
476     string purgSumTitle = MemoryFilter::GetInstance().PURGSUM_OUT_LABEL + ":";
477     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, purgSumTitle);
478     purgSum.push_back(purgSumTitle);
479     purgSum.push_back(AddKbUnit(GetProcValue(pid, MemoryFilter::GetInstance().PURGSUM_OUT_LABEL)));
480     result->push_back(purgSum);
481 
482     vector<string> purgPin;
483     string purgPinTitle = MemoryFilter::GetInstance().PURGPIN_OUT_LABEL + ":";
484     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, purgPinTitle);
485     purgPin.push_back(purgPinTitle);
486     purgPin.push_back(AddKbUnit(GetProcValue(pid, MemoryFilter::GetInstance().PURGPIN_OUT_LABEL)));
487     result->push_back(purgPin);
488 }
489 
GetNativeValue(const string & tag,const GroupMap & nativeGroupMap,StringMatrix result)490 void MemoryInfo::GetNativeValue(const string& tag, const GroupMap& nativeGroupMap, StringMatrix result)
491 {
492     vector<string> heap;
493     string heapTitle = tag + ":";
494     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, heapTitle);
495     heap.push_back(heapTitle);
496 
497     auto info = nativeGroupMap.find(tag);
498     if (info == nativeGroupMap.end()) {
499         DUMPER_HILOGE(MODULE_SERVICE, "GetNativeValue fail! tag = %{public}s", tag.c_str());
500         return;
501     }
502     string nativeValue;
503     auto &valueMap = info->second;
504     for (const auto &key : MemoryFilter::GetInstance().VALUE_WITH_PID) {
505         auto it = valueMap.find(key);
506         string value = "0";
507         if (it != valueMap.end()) {
508             value = to_string(it->second);
509         }
510         StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, value);
511         nativeValue += value;
512     }
513 
514     heap.push_back(nativeValue);
515     result->push_back(heap);
516 }
517 
GetNativeHeap(const GroupMap & nativeGroupMap,StringMatrix result)518 void MemoryInfo::GetNativeHeap(const GroupMap& nativeGroupMap, StringMatrix result)
519 {
520     AddBlankLine(result);
521     vector<string> title;
522     title.push_back(MemoryFilter::GetInstance().NATIVE_HEAP_LABEL + ":");
523     result->push_back(title);
524     for (const auto &it: NATIVE_HEAP_TAG_) {
525         GetNativeValue(it, nativeGroupMap, result);
526     }
527 }
528 
GetDmaByPid(const int32_t & pid,StringMatrix result)529 void MemoryInfo::GetDmaByPid(const int32_t &pid, StringMatrix result)
530 {
531     AddBlankLine(result);
532     vector<string> title;
533     title.push_back(MemoryFilter::GetInstance().DMA_TAG + ":");
534     result->push_back(title);
535 
536     vector<string> dma;
537     string dmaTitle = MemoryFilter::GetInstance().DMA_OUT_LABEL + ":";
538     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, dmaTitle);
539     dma.push_back(dmaTitle);
540     dma.push_back(AddKbUnit(dmaInfo_.GetDmaByPid(pid)));
541     result->push_back(dma);
542 }
543 
GetHiaiServerIon(const int32_t & pid,StringMatrix result)544 void MemoryInfo::GetHiaiServerIon(const int32_t &pid, StringMatrix result)
545 {
546     if (GetProcName(pid) != "hiaiserver") {
547         return;
548     }
549     void *handle = dlopen(LIB.c_str(), RTLD_LAZY);
550     if (handle == nullptr) {
551         DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s.", LIB.c_str());
552         return;
553     }
554     HiaiFunc pfn = reinterpret_cast<HiaiFunc>(dlsym(handle, HIAI_MEM_INFO_FN));
555     if (pfn == nullptr) {
556         DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym %{public}s.", HIAI_MEM_INFO_FN);
557         dlclose(handle);
558         return;
559     }
560     MemInfoData::HiaiUserAllocatedMemInfo memInfos[HIAI_MAX_QUERIED_USER_MEMINFO_LIMIT] = {};
561 
562     int realSize = 0;
563     pfn(memInfos, HIAI_MAX_QUERIED_USER_MEMINFO_LIMIT, &realSize);
564     if (realSize > 0) {
565         AddBlankLine(result);
566         vector<string> vecIon;
567         vecIon.push_back("HIAIServer ION:\n");
568         for (int i = 0; i < realSize; i++) {
569             vecIon.push_back(GetProcName(memInfos[i].pid) + "(" + to_string(memInfos[i].pid) + "):" +
570                              to_string(memInfos[i].size / BYTE_PER_KB) + " kB\n");
571         }
572         result->push_back(vecIon);
573     }
574     dlclose(handle);
575 }
576 
GetRamCategory(const GroupMap & smapsInfos,const ValueMap & meminfos,StringMatrix result)577 void MemoryInfo::GetRamCategory(const GroupMap &smapsInfos, const ValueMap &meminfos, StringMatrix result)
578 {
579     SaveStringToFd(rawParamFd_, "Total RAM by Category:\n");
580 
581     bool hardWareSuccess = GetHardWareUsage(result);
582     if (!hardWareSuccess) {
583         DUMPER_HILOGE(MODULE_SERVICE, "Get hardWare usage fail.\n");
584     }
585 
586     bool cmaSuccess = GetCMAUsage(result);
587     if (!cmaSuccess) {
588         DUMPER_HILOGE(MODULE_SERVICE, "Get CMA fail.\n");
589     }
590 
591     bool kernelSuccess = GetKernelUsage(meminfos, result);
592     if (!kernelSuccess) {
593         DUMPER_HILOGE(MODULE_SERVICE, "Get kernel usage fail.\n");
594     }
595 
596     GetProcesses(smapsInfos, result);
597 }
598 
AddBlankLine(StringMatrix result)599 void MemoryInfo::AddBlankLine(StringMatrix result)
600 {
601     vector<string> blank;
602     blank.push_back("\n");
603     result->push_back(blank);
604 }
605 
GetProcName(const int32_t & pid)606 string MemoryInfo::GetProcName(const int32_t &pid)
607 {
608     string procName = UNKNOWN_PROCESS;
609     DumpCommonUtils::GetProcessNameByPid(pid, procName);
610     if (procName == UNKNOWN_PROCESS) {
611         string path = "/proc/" + to_string(pid) + "/status";
612         procName = FileUtils::GetInstance().GetProcValue(pid, path, "Name");
613     }
614     return procName;
615 }
616 
GetProcValue(const int32_t & pid,const string & key)617 uint64_t MemoryInfo::GetProcValue(const int32_t &pid, const string& key)
618 {
619     string path = "/proc/" + to_string(pid) + "/status";
620     std::string value = FileUtils::GetInstance().GetProcValue(pid, path, key);
621     if (value == UNKNOWN_PROCESS) {
622         DUMPER_HILOGE(MODULE_SERVICE, "GetProcStatusValue failed");
623         return 0;
624     }
625     int number = 0;
626     value = value.substr(0, value.size() - 3); // 3: ' kB'
627     if (value.find_last_of(' ') != std::string::npos) {
628         value = value.substr(value.find_last_of(' ') + 1);
629     }
630     if (!StrToInt(value, number)) {
631         DUMPER_HILOGE(MODULE_COMMON, "StrToInt failed, value: %{public}s", value.c_str());
632         return 0;
633     }
634     return static_cast<uint64_t>(number);
635 }
636 
GetProcessAdjLabel(const int32_t pid)637 string MemoryInfo::GetProcessAdjLabel(const int32_t pid)
638 {
639     string adjLabel = RECLAIM_PRIORITY_UNKNOWN_DESC;
640     string fillPath = "/proc/" + to_string(pid) + "/oom_score_adj";
641     if (!DumpUtils::PathIsValid(fillPath)) {
642         DUMPER_HILOGE(MODULE_COMMON, "GetProcessAdjLabel leave|false, PathIsValid");
643         return adjLabel;
644     }
645     auto fp = fopen(fillPath.c_str(), "rb");
646     if (fp == nullptr) {
647         DUMPER_HILOGE(MODULE_COMMON, "Open oom_score_adj failed.");
648         return adjLabel;
649     }
650     constexpr int bufSize = 128; // 128: buf size
651     char buf[bufSize] = {0};
652     size_t readSum = fread(buf, 1, bufSize, fp);
653     (void)fclose(fp);
654     fp = nullptr;
655     if (readSum < 1) {
656         DUMPER_HILOGE(MODULE_COMMON, "Read oom_score_adj failed.");
657         return adjLabel;
658     }
659     int value = RECLAIM_PRIORITY_UNKNOWN;
660     std::string label(buf);
661     if (label.empty()) {
662         DUMPER_HILOGE(MODULE_COMMON, "label is empty.");
663         return adjLabel;
664     }
665     if (!StrToInt(label.substr(0, label.size() - 1), value)) {
666         DUMPER_HILOGE(MODULE_COMMON, "StrToInt failed.");
667         return adjLabel;
668     }
669     adjLabel = GetReclaimPriorityString(value);
670     return adjLabel;
671 }
672 
GetPids()673 bool MemoryInfo::GetPids()
674 {
675     bool success = DumpCommonUtils::GetUserPids(pids_);
676     if (!success) {
677         DUMPER_HILOGE(MODULE_SERVICE, "GetPids error");
678     }
679     return success;
680 }
681 
GetVss(const int32_t & pid)682 uint64_t MemoryInfo::GetVss(const int32_t &pid)
683 {
684     string path = "/proc/" + to_string(pid) + "/statm";
685     uint64_t res = 0;
686     bool ret = FileUtils::GetInstance().LoadStringFromProcCb(path, true, true, [&](const string& line) -> void {
687         if (!line.empty()) {
688             uint64_t tempValue = 0;
689             int retScanf = sscanf_s(line.c_str(), "%llu^*", &tempValue);
690             if (retScanf != -1) {
691                 res = tempValue * VSS_BIT;
692             } else {
693                 DUMPER_HILOGE(MODULE_SERVICE, "GetVss error! pid = %{public}d", pid);
694             }
695         }
696     });
697     if (!ret) {
698         return 0;
699     }
700     return res;
701 }
702 
GetGraphicsMemory(int32_t pid,MemInfoData::GraphicsMemory & graphicsMemory)703 bool MemoryInfo::GetGraphicsMemory(int32_t pid, MemInfoData::GraphicsMemory &graphicsMemory)
704 {
705     if ((IsRenderService(pid))) {
706 #ifdef HIDUMPER_GRAPHIC_ENABLE
707         GetMemGraphics();
708 #endif
709         GetRenderServiceGraphics(pid, graphicsMemory);
710         if (graphicsMemory.gl > g_sumPidsMemGL) {
711             graphicsMemory.gl -= g_sumPidsMemGL;
712         } else {
713             DUMPER_HILOGE(MODULE_SERVICE, "GL: %{public}d, sum pid GL: %{public}d",
714                 static_cast<int>(graphicsMemory.gl), static_cast<int>(g_sumPidsMemGL));
715         }
716     } else {
717         GetRenderServiceGraphics(pid, graphicsMemory);
718 #ifdef HIDUMPER_GRAPHIC_ENABLE
719         auto& rsClient = Rosen::RSInterfaces::GetInstance();
720         unique_ptr<MemoryGraphic> memGraphic = make_unique<MemoryGraphic>(rsClient.GetMemoryGraphic(pid));
721         graphicsMemory.gl += memGraphic-> GetGpuMemorySize() / BYTE_PER_KB;
722 #endif
723     }
724     return true;
725 }
726 
GetMemByProcessPid(const int32_t & pid,const DmaInfo & dmaInfo,MemInfoData::MemUsage & usage)727 bool MemoryInfo::GetMemByProcessPid(const int32_t &pid, const DmaInfo &dmaInfo, MemInfoData::MemUsage &usage)
728 {
729     bool success = false;
730     MemInfoData::MemInfo memInfo;
731     unique_ptr<ParseSmapsRollupInfo> getSmapsRollup = make_unique<ParseSmapsRollupInfo>();
732     if (getSmapsRollup->GetMemInfo(pid, memInfo)) {
733         usage.vss = GetVss(pid);
734         usage.uss = memInfo.privateClean + memInfo.privateDirty;
735         usage.rss = memInfo.rss;
736         usage.pss = memInfo.pss;
737         usage.swapPss = memInfo.swapPss;
738         usage.dma = dmaInfo.GetDmaByPid(pid);
739         usage.name = GetProcName(pid);
740         usage.pid = pid;
741         usage.adjLabel = GetProcessAdjLabel(pid);
742         success = true;
743     }
744 
745     MemInfoData::GraphicsMemory graphicsMemory;
746     MemoryUtil::GetInstance().InitGraphicsMemory(graphicsMemory);
747     graphicsMemory.graph = dmaInfo_.GetDmaByPid(pid);
748     if (GetGraphicsMemory(pid, graphicsMemory)) {
749         usage.gl = graphicsMemory.gl;
750         usage.graph = graphicsMemory.graph;
751         usage.uss = usage.uss + graphicsMemory.gl + graphicsMemory.graph;
752         usage.pss = usage.pss + graphicsMemory.gl + graphicsMemory.graph;
753         usage.rss = usage.rss + graphicsMemory.gl + graphicsMemory.graph;
754         DUMPER_HILOGD(MODULE_SERVICE, "uss:%{public}d pss:%{public}d rss:%{public}d gl:%{public}d graph:%{public}d",
755                       static_cast<int>(usage.uss), static_cast<int>(usage.pss), static_cast<int>(usage.rss),
756                       static_cast<int>(graphicsMemory.gl), static_cast<int>(graphicsMemory.graph));
757     }
758     return success;
759 }
760 
MemUsageToMatrix(const MemInfoData::MemUsage & memUsage,StringMatrix result)761 void MemoryInfo::MemUsageToMatrix(const MemInfoData::MemUsage &memUsage, StringMatrix result)
762 {
763     string pid = to_string(memUsage.pid);
764     StringUtils::GetInstance().SetWidth(PID_WIDTH_, BLANK_, true, pid);
765 
766     uint64_t pss = memUsage.pss + memUsage.swapPss;
767     string totalPss = to_string(pss) + "(" + to_string(memUsage.swapPss) + " in SwapPss) kB";
768     StringUtils::GetInstance().SetWidth(PSS_WIDTH_, BLANK_, false, totalPss);
769 
770     uint64_t vss = memUsage.vss;
771     string totalVss = AddKbUnit(vss);
772     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalVss);
773 
774     uint64_t rss = memUsage.rss;
775     string totalRss = AddKbUnit(rss);
776     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalRss);
777 
778     uint64_t uss = memUsage.uss;
779     string totalUss = AddKbUnit(uss);
780     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalUss);
781 
782     uint64_t gl = memUsage.gl;
783     string unMappedGL = AddKbUnit(gl);
784     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGL);
785 
786     uint64_t graph = memUsage.graph;
787     string unMappedGraph = AddKbUnit(graph);
788     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGraph);
789 
790     uint64_t dma = memUsage.dma;
791     string unMappedDma = AddKbUnit(dma);
792     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedDma);
793 
794     uint64_t purgSum = memUsage.purgSum;
795     string unMappedPurgSum = AddKbUnit(purgSum);
796     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgSum);
797 
798     uint64_t purgPin = memUsage.purgPin;
799     string unMappedPurgPin = AddKbUnit(purgPin);
800     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgPin);
801 
802     string name = "    " + memUsage.name;
803     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, name);
804 
805     (void)dprintf(rawParamFd_, "%s%s%s%s%s%s%s%s%s%s%s\n", pid.c_str(),
806         totalPss.c_str(), totalVss.c_str(), totalRss.c_str(), totalUss.c_str(),
807         unMappedGL.c_str(), unMappedGraph.c_str(), unMappedDma.c_str(), unMappedPurgSum.c_str(),
808         unMappedPurgPin.c_str(), name.c_str());
809 }
810 
AddMemByProcessTitle(StringMatrix result,string sortType)811 void MemoryInfo::AddMemByProcessTitle(StringMatrix result, string sortType)
812 {
813     string processTitle = "Total Memory Usage by " + sortType + ":";
814     (void)dprintf(rawParamFd_, "%s\n", processTitle.c_str());
815 
816     string pid = "PID";
817     StringUtils::GetInstance().SetWidth(PID_WIDTH_, BLANK_, true, pid);
818 
819     string totalPss = "Total Pss(xxx in SwapPss)";
820     StringUtils::GetInstance().SetWidth(PSS_WIDTH_, BLANK_, false, totalPss);
821 
822     string totalVss = "Total Vss";
823     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalVss);
824 
825     string totalRss = "Total Rss";
826     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalRss);
827 
828     string totalUss = "Total Uss";
829     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalUss);
830 
831     string unMappedGL = MemoryFilter::GetInstance().GL_OUT_LABEL;
832     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGL);
833 
834     string unMappedGraph = MemoryFilter::GetInstance().GRAPH_OUT_LABEL;
835     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGraph);
836 
837     string unMappedDma = MemoryFilter::GetInstance().DMA_OUT_LABEL;
838     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedDma);
839 
840     string unMappedPurgSum = MemoryFilter::GetInstance().PURGSUM_OUT_LABEL;
841     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgSum);
842 
843     string unMappedPurgPin = MemoryFilter::GetInstance().PURGPIN_OUT_LABEL;
844     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgPin);
845 
846     string name = "    Name";
847     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, name);
848 
849     (void)dprintf(rawParamFd_, "%s%s%s%s%s%s%s%s%s%s%s\n", pid.c_str(),
850         totalPss.c_str(), totalVss.c_str(), totalRss.c_str(), totalUss.c_str(),
851         unMappedGL.c_str(), unMappedGraph.c_str(), unMappedDma.c_str(), unMappedPurgSum.c_str(),
852         unMappedPurgPin.c_str(), name.c_str());
853 }
854 
855 #ifdef HIDUMPER_GRAPHIC_ENABLE
GetMemGraphics()856 void MemoryInfo::GetMemGraphics()
857 {
858     memGraphicVec_.clear();
859     auto& rsClient = Rosen::RSInterfaces::GetInstance();
860     memGraphicVec_ = rsClient.GetMemoryGraphics();
861     auto sumPidsMemGL = 0;
862     for (auto it = memGraphicVec_.begin(); it != memGraphicVec_.end(); it++) {
863         sumPidsMemGL += it->GetGpuMemorySize();
864     }
865     g_sumPidsMemGL = static_cast<uint64_t>(sumPidsMemGL / BYTE_PER_KB);
866 }
867 #endif
868 
GetMemoryInfoNoPid(int fd,StringMatrix result)869 DumpStatus MemoryInfo::GetMemoryInfoNoPid(int fd, StringMatrix result)
870 {
871     std::lock_guard<std::mutex> lock(mutex_);
872     rawParamFd_ = fd;
873     (void)dprintf(rawParamFd_, "%s\n", MEMORY_LINE.c_str());
874     if (!dmaInfo_.ParseDmaInfo()) {
875         DUMPER_HILOGE(MODULE_SERVICE, "Parse dma info error\n");
876     }
877     if (!isReady_) {
878         memUsages_.clear();
879         pids_.clear();
880         totalGL_ = 0;
881         totalGraph_ = 0;
882         AddMemByProcessTitle(result, "PID");
883         if (!GetPids()) {
884             return DUMP_FAIL;
885         }
886 #ifdef HIDUMPER_GRAPHIC_ENABLE
887         GetMemGraphics();
888 #endif
889         isReady_ = true;
890     }
891 
892     if (!dumpSmapsOnStart_) {
893         dumpSmapsOnStart_ = true;
894         std::promise<GroupMap> promise;
895         fut_ = promise.get_future();
896         std::thread([promise = std::move(promise), this]() mutable {
897             GroupMap groupMap;
898             std::vector<int32_t> pids(this->pids_);
899             for (auto pid : pids) {
900                 GetSmapsInfoNoPid(pid, groupMap);
901             }
902             promise.set_value(groupMap);
903             }).detach();
904     }
905     MemInfoData::MemUsage usage;
906     MemoryUtil::GetInstance().InitMemUsage(usage);
907     for (auto pid : pids_) {
908         if (GetMemByProcessPid(pid, dmaInfo_, usage)) {
909             memUsages_.push_back(usage);
910             adjMemResult_[usage.adjLabel].push_back(usage);
911             totalGL_ += usage.gl;
912             totalGraph_ += usage.graph;
913             MemUsageToMatrix(usage, result);
914         } else {
915             DUMPER_HILOGE(MODULE_SERVICE, "Get smaps_rollup error! pid = %{public}d\n", static_cast<int>(pid));
916         }
917     }
918     return DealResult(result);
919 }
920 
DealResult(StringMatrix result)921 DumpStatus MemoryInfo::DealResult(StringMatrix result)
922 {
923     ValueMap meminfoResult;
924     if (!GetMeminfo(meminfoResult)) {
925         DUMPER_HILOGE(MODULE_SERVICE, "Get meminfo error\n");
926         return DUMP_FAIL;
927     }
928 
929     GetSortedMemoryInfoNoPid(result);
930     SaveStringToFd(rawParamFd_, "\n");
931     GetMemoryByAdj(result);
932     SaveStringToFd(rawParamFd_, "\n");
933 
934     GroupMap smapsResult = fut_.get();
935 
936     GetPssTotal(smapsResult, result);
937     SaveStringToFd(rawParamFd_, "\n");
938 
939     GetRamUsage(smapsResult, meminfoResult, result);
940     SaveStringToFd(rawParamFd_, "\n");
941 
942     GetRamCategory(smapsResult, meminfoResult, result);
943     SaveStringToFd(rawParamFd_, "\n");
944 
945     GetPurgTotal(meminfoResult, result);
946 
947     isReady_ = false;
948     dumpSmapsOnStart_ = false;
949     memUsages_.clear();
950     smapsResult.clear();
951     return DUMP_OK;
952 }
953 
GetSortedMemoryInfoNoPid(StringMatrix result)954 void MemoryInfo::GetSortedMemoryInfoNoPid(StringMatrix result)
955 {
956     SaveStringToFd(rawParamFd_, "\n");
957     AddMemByProcessTitle(result, "Size");
958 
959     std::sort(memUsages_.begin(), memUsages_.end(),
960         [] (MemInfoData::MemUsage &left, MemInfoData::MemUsage &right) {
961         if (right.pss + right.swapPss != left.pss + left.swapPss) {
962             return right.pss + right.swapPss < left.pss + left.swapPss;
963         }
964         if (right.vss != left.vss) {
965             return right.vss < left.vss;
966         }
967         if (right.rss != left.rss) {
968             return right.rss < left.rss;
969         }
970         if (right.uss != left.uss) {
971             return right.uss < left.uss;
972         }
973         return right.pid < left.pid;
974     });
975 
976     for (auto &memUsage : memUsages_) {
977         MemUsageToMatrix(memUsage, result);
978     }
979 }
980 
GetMemoryByAdj(StringMatrix result)981 void MemoryInfo::GetMemoryByAdj(StringMatrix result)
982 {
983     SaveStringToFd(rawParamFd_, "Total Pss by OOM adjustment:\n");
984 
985     vector<string> reclaimPriority_;
986     for (auto reclaim : ReclaimPriorityMapping) {
987         reclaimPriority_.push_back(reclaim.second);
988     }
989     reclaimPriority_.push_back(RECLAIM_PRIORITY_UNKNOWN_DESC);
990 
991     for (const auto &adjLabel : reclaimPriority_) {
992         vector<MemInfoData::MemUsage> memUsages = adjMemResult_[adjLabel];
993         vector<string> label;
994         if (memUsages.size() == 0) {
995             SaveStringToFd(rawParamFd_, adjLabel + ": " + AddKbUnit(0) + "\n");
996             continue;
997         }
998         uint64_t totalPss = accumulate(memUsages.begin(), memUsages.end(), (uint64_t)0,
999         [] (uint64_t a, MemInfoData::MemUsage &b) {
1000             return a + b.pss + b.swapPss;
1001         });
1002         SaveStringToFd(rawParamFd_, adjLabel + ": " + AddKbUnit(totalPss) + "\n");
1003 
1004         std::sort(memUsages.begin(), memUsages.end(),
1005             [] (MemInfoData::MemUsage &left, MemInfoData::MemUsage &right) {
1006             return right.pss + right.swapPss < left.pss + left.swapPss;
1007         });
1008         for (const auto &memUsage : memUsages) {
1009             string name = PRE_BLANK + memUsage.name + "(pid=" + to_string(memUsage.pid) + "): ";
1010             StringUtils::GetInstance().SetWidth(NAME_AND_PID_WIDTH, BLANK_, true, name);
1011             name += AddKbUnit(memUsage.pss + memUsage.swapPss);
1012             if (memUsage.swapPss > 0) {
1013                 name += " (" + to_string(memUsage.swapPss) + " kB in SwapPss)";
1014             }
1015             SaveStringToFd(rawParamFd_, name + "\n");
1016         }
1017     }
1018 }
1019 
GetReclaimPriorityString(int32_t priority)1020 std::string MemoryInfo::GetReclaimPriorityString(int32_t priority)
1021 {
1022     if (priority < RECLAIM_PRIORITY_SYSTEM || priority > RECLAIM_PRIORITY_UNKNOWN) {
1023         return RECLAIM_PRIORITY_UNKNOWN_DESC;
1024     } else if (priority < RECLAIM_ONDEMAND_SYSTEM) {
1025         return ReclaimPriorityMapping.at(RECLAIM_PRIORITY_SYSTEM);
1026     } else if (priority < RECLAIM_PRIORITY_KILLABLE_SYSTEM) {
1027         return ReclaimPriorityMapping.at(RECLAIM_ONDEMAND_SYSTEM);
1028     } else if (priority < RECLAIM_PRIORITY_FOREGROUND) {
1029         return ReclaimPriorityMapping.at(RECLAIM_PRIORITY_KILLABLE_SYSTEM);
1030     } else if (priority < RECLAIM_PRIORITY_VISIBLE) {
1031         return ReclaimPriorityMapping.at(RECLAIM_PRIORITY_FOREGROUND);
1032     } else if (priority < RECLAIM_PRIORITY_BG_SUSPEND_DELAY) {
1033         return ReclaimPriorityMapping.at(RECLAIM_PRIORITY_VISIBLE);
1034     } else if (priority < RECLAIM_PRIORITY_BG_PERCEIVED) {
1035         return ReclaimPriorityMapping.at(RECLAIM_PRIORITY_BG_SUSPEND_DELAY);
1036     } else if (priority < RECLAIM_PRIORITY_BG_DIST_DEVICE) {
1037         return ReclaimPriorityMapping.at(RECLAIM_PRIORITY_BG_PERCEIVED);
1038     } else if (priority < RECLAIM_PRIORITY_BACKGROUND) {
1039         return ReclaimPriorityMapping.at(RECLAIM_PRIORITY_BG_DIST_DEVICE);
1040     } else {
1041         return ReclaimPriorityMapping.at(RECLAIM_PRIORITY_BACKGROUND);
1042     }
1043 }
1044 
SetPss(MemInfoData::MemInfo & meminfo,uint64_t value)1045 void MemoryInfo::SetPss(MemInfoData::MemInfo &meminfo, uint64_t value)
1046 {
1047     meminfo.pss += value;
1048 }
1049 
SetSharedClean(MemInfoData::MemInfo & meminfo,uint64_t value)1050 void MemoryInfo::SetSharedClean(MemInfoData::MemInfo &meminfo, uint64_t value)
1051 {
1052     meminfo.sharedClean += value;
1053 }
1054 
SetSharedDirty(MemInfoData::MemInfo & meminfo,uint64_t value)1055 void MemoryInfo::SetSharedDirty(MemInfoData::MemInfo &meminfo, uint64_t value)
1056 {
1057     meminfo.sharedDirty += value;
1058 }
1059 
SetPrivateClean(MemInfoData::MemInfo & meminfo,uint64_t value)1060 void MemoryInfo::SetPrivateClean(MemInfoData::MemInfo &meminfo, uint64_t value)
1061 {
1062     meminfo.privateClean += value;
1063 }
1064 
SetPrivateDirty(MemInfoData::MemInfo & meminfo,uint64_t value)1065 void MemoryInfo::SetPrivateDirty(MemInfoData::MemInfo &meminfo, uint64_t value)
1066 {
1067     meminfo.privateDirty += value;
1068 }
1069 
SetSwap(MemInfoData::MemInfo & meminfo,uint64_t value)1070 void MemoryInfo::SetSwap(MemInfoData::MemInfo &meminfo, uint64_t value)
1071 {
1072     meminfo.swap += value;
1073 }
1074 
SetSwapPss(MemInfoData::MemInfo & meminfo,uint64_t value)1075 void MemoryInfo::SetSwapPss(MemInfoData::MemInfo &meminfo, uint64_t value)
1076 {
1077     meminfo.swapPss += value;
1078 }
SetHeapSize(MemInfoData::MemInfo & meminfo,uint64_t value)1079 void MemoryInfo::SetHeapSize(MemInfoData::MemInfo &meminfo, uint64_t value)
1080 {
1081     meminfo.heapSize += value;
1082 }
1083 
SetHeapAlloc(MemInfoData::MemInfo & meminfo,uint64_t value)1084 void MemoryInfo::SetHeapAlloc(MemInfoData::MemInfo &meminfo, uint64_t value)
1085 {
1086     meminfo.heapAlloc += value;
1087 }
1088 
SetHeapFree(MemInfoData::MemInfo & meminfo,uint64_t value)1089 void MemoryInfo::SetHeapFree(MemInfoData::MemInfo &meminfo, uint64_t value)
1090 {
1091     meminfo.heapFree += value;
1092 }
1093 } // namespace HiviewDFX
1094 } // namespace OHOS
1095