1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "memory_catcher.h"
16
17 #include "collect_result.h"
18 #include "file_util.h"
19 #include "freeze_common.h"
20 #include "hiview_logger.h"
21 #include "memory_collector.h"
22 #include "string_util.h"
23
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace {
27 constexpr const char* ASHMEM_PATH = "/proc/ashmem_process_info";
28 constexpr const char* DMAHEAP_PATH = "/proc/dmaheap_process_info";
29 constexpr const char* GPUMEM_PATH = "/proc/gpumem_process_info";
30 constexpr const char* ASHMEM = "AshmemUsed";
31 constexpr const char* DMAHEAP = "DmaHeapTotalUsed";
32 constexpr const char* GPUMEM = "GpuTotalUsed";
33 constexpr const char* RECLAIM = "ReclaimAvailBuffer";
34 constexpr const char* LONG_PRESS = "LONG_PRESS";
35 constexpr const char* AP_S_PRESS6S = "AP_S_PRESS6S";
36 constexpr const char* PROC_PRESSURE_MEMORY = "/proc/pressure/memory";
37 constexpr const char* PROC_MEMORYVIEW = "/proc/memview";
38 constexpr const char* PROC_MEMORYINFO = "/proc/meminfo";
39 constexpr int OVER_MEM_SIZE = 2 * 1024 * 1024;
40 constexpr int BELOW_MEM_SIZE = 500 * 1024;
41 constexpr int DECIMAL = 10;
42 }
43 #ifdef USAGE_CATCHER_ENABLE
44 using namespace UCollect;
45 using namespace UCollectUtil;
46 DEFINE_LOG_LABEL(0xD002D01, "EventLogger-MemoryCatcher");
MemoryCatcher()47 MemoryCatcher::MemoryCatcher() : EventLogCatcher()
48 {
49 name_ = "MemoryCatcher";
50 }
51
Initialize(const std::string & strParam1,int intParam1,int intParam2)52 bool MemoryCatcher::Initialize(const std::string& strParam1, int intParam1, int intParam2)
53 {
54 // this catcher do not need parameters, just return true
55 description_ = "MemoryCatcher --\n";
56 return true;
57 }
58
Catch(int fd,int jsonFd)59 int MemoryCatcher::Catch(int fd, int jsonFd)
60 {
61 int originSize = GetFdSize(fd);
62 std::string freezeMemory;
63 std::string content;
64 if (event_) {
65 freezeMemory = event_->GetEventValue("FREEZE_MEMORY");
66 size_t tagIndex = freezeMemory.find("Get freeze memory end time:");
67 std::string splitStr = "\\n";
68 size_t procStatmIndex = freezeMemory.rfind(splitStr);
69 if (tagIndex != std::string::npos && procStatmIndex != std::string::npos && procStatmIndex > tagIndex) {
70 content = freezeMemory.substr(0, procStatmIndex);
71 event_->SetEventValue("PROC_STATM", freezeMemory.substr(procStatmIndex + splitStr.size()));
72 }
73 }
74 content = freezeMemory.empty() ? CollectFreezeSysMemory() : content;
75 std::string data;
76 if (!content.empty()) {
77 std::vector<std::string> vec;
78 StringUtil::SplitStr(content, "\\n", vec);
79 for (const std::string& mem : vec) {
80 FileUtil::SaveStringToFd(fd, mem + "\n");
81 CheckString(mem, data, ASHMEM, ASHMEM_PATH);
82 CheckString(mem, data, DMAHEAP, DMAHEAP_PATH);
83 CheckString(mem, data, GPUMEM, GPUMEM_PATH);
84 CheckString(mem, data, RECLAIM, "");
85 }
86 }
87 if (!data.empty()) {
88 FreezeCommon::WriteTimeInfoToFd(fd, "collect ashmem dmaheap gpumem start time: ");
89 FileUtil::SaveStringToFd(fd, data);
90 FreezeCommon::WriteTimeInfoToFd(fd, "\ncollect ashmem dmaheap gpumem end time: ", false);
91 } else {
92 FileUtil::SaveStringToFd(fd, "don't collect ashmem dmaheap gpumem\n");
93 }
94 logSize_ = GetFdSize(fd) - originSize;
95 return logSize_;
96 }
97
CollectMemInfo()98 void MemoryCatcher::CollectMemInfo()
99 {
100 HIVIEW_LOGI("CollectMemInfo start");
101 std::shared_ptr<MemoryCollector> collector = MemoryCollector::Create();
102 collector->CollectRawMemInfo();
103 collector->ExportMemView();
104 HIVIEW_LOGI("CollectMemInfo end");
105 }
106
SetEvent(std::shared_ptr<SysEvent> event)107 void MemoryCatcher::SetEvent(std::shared_ptr<SysEvent> event)
108 {
109 event_ = event;
110 }
111
GetStringFromFile(const std::string & path)112 std::string MemoryCatcher::GetStringFromFile(const std::string &path)
113 {
114 std::string content;
115 FileUtil::LoadStringFromFile(path, content);
116 return content;
117 }
118
GetNumFromString(const std::string & mem)119 int MemoryCatcher::GetNumFromString(const std::string &mem)
120 {
121 int num = 0;
122 int digit = 0;
123 int maxDivTen = INT_MAX / DECIMAL;
124 int maxLastDigit = INT_MAX % DECIMAL;
125
126 for (const char &c : mem) {
127 if (!isdigit(c)) {
128 continue;
129 }
130 digit = c - '0';
131 if (num > maxDivTen || (num == maxDivTen && digit > maxLastDigit)) {
132 return INT_MAX;
133 }
134 num = num * DECIMAL + digit;
135 }
136 return num;
137 }
138
CheckString(const std::string & mem,std::string & data,const std::string & key,const std::string & path)139 void MemoryCatcher::CheckString(
140 const std::string &mem, std::string &data, const std::string &key, const std::string &path)
141 {
142 if (mem.find(key) != std::string::npos) {
143 int memsize = GetNumFromString(mem);
144 if (!path.empty() && memsize > OVER_MEM_SIZE) {
145 data += GetStringFromFile(path);
146 }
147 if (path.empty() && memsize < BELOW_MEM_SIZE && event_) {
148 event_->SetEventValue(FreezeCommon::HOST_RESOURCE_WARNING, "Yes");
149 }
150 }
151 }
152
CollectFreezeSysMemory()153 std::string MemoryCatcher::CollectFreezeSysMemory()
154 {
155 std::string memInfoPath = FileUtil::FileExists(PROC_MEMORYVIEW) ? PROC_MEMORYVIEW : PROC_MEMORYINFO;
156 std::string content = GetStringFromFile(PROC_PRESSURE_MEMORY) + "\n" + GetStringFromFile(memInfoPath);
157 return content;
158 }
159 #endif // USAGE_CATCHER_ENABLE
160 } // namespace HiviewDFX
161 } // namespace OHOS
162