1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "native_memory_profiler_sa_client_manager.h"
17
18 #include "native_memory_profiler_sa_proxy.h"
19
20 #include "logging.h"
21
22 #include <iostream>
23 #include <sstream>
24
25 namespace OHOS::Developtools::NativeDaemon {
26 namespace {
27 constexpr uint32_t LIB_SMS = 4096;
28 constexpr uint32_t CALL_STACK_SMS = 16384;
29 constexpr uint32_t NMD_DURATION = 5;
30 constexpr uint32_t NMD_SHMEM = 300;
31 constexpr int ONLY_NMD = 2;
32 constexpr int SIMP_NMD = 3;
33 constexpr int FIVE_MINUTES = 300;
34 constexpr int JS_STACK_DEPS = 10;
35 }
36
Start(std::shared_ptr<NativeMemoryProfilerSaConfig> & config)37 int32_t NativeMemoryProfilerSaClientManager::Start(std::shared_ptr<NativeMemoryProfilerSaConfig>& config)
38 {
39 CHECK_NOTNULL(config, RET_ERR, "NativeMemoryProfilerSaClientManager: config is nullptr");
40 CHECK_TRUE(CheckConfig(config), RET_ERR, "CheckConfig failed");
41 auto service = GetRemoteService();
42 if (service == nullptr) {
43 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaClientManager: start GetRemoteService failed");
44 return RET_ERR;
45 }
46 NativeMemoryProfilerSaProxy proxy(service);
47 return proxy.Start(config);
48 }
49
Start(NativeMemProfilerType type,uint32_t pid,uint32_t duration,uint32_t sampleIntervel)50 int32_t NativeMemoryProfilerSaClientManager::Start(NativeMemProfilerType type, uint32_t pid, uint32_t duration,
51 uint32_t sampleIntervel)
52 {
53 if (pid == 0) {
54 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaClientManager: pid cannot be 0");
55 return RET_ERR;
56 }
57 auto config = std::make_shared<NativeMemoryProfilerSaConfig>();
58 CHECK_NOTNULL(config, RET_ERR, "NativeMemoryProfilerSaClientManager: config is nullptr");
59 config->pid_ = static_cast<int32_t>(pid);
60 config->duration_ = duration;
61 config->sampleInterval_ = sampleIntervel;
62 if (type == NativeMemProfilerType::MEM_PROFILER_LIBRARY) {
63 config->responseLibraryMode_ = true;
64 } else if (type == NativeMemProfilerType::MEM_PROFILER_CALL_STACK) {
65 config->responseLibraryMode_ = false;
66 }
67 return Start(config);
68 }
69
Stop(uint32_t pid)70 int32_t NativeMemoryProfilerSaClientManager::Stop(uint32_t pid)
71 {
72 CHECK_TRUE(pid != 0, RET_ERR, "NativeMemoryProfilerSaClientManager: pid is 0");
73 auto service = GetRemoteService();
74 if (service == nullptr) {
75 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaClientManager: stop GetRemoteService failed");
76 return RET_ERR;
77 }
78 NativeMemoryProfilerSaProxy proxy(service);
79 return proxy.Stop(pid);
80 }
81
Stop(const std::string & name)82 int32_t NativeMemoryProfilerSaClientManager::Stop(const std::string& name)
83 {
84 CHECK_TRUE(!name.empty(), RET_ERR, "NativeMemoryProfilerSaClientManager: name is empty");
85 auto service = GetRemoteService();
86 if (service == nullptr) {
87 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaClientManager: stop GetRemoteService failed");
88 return RET_ERR;
89 }
90 NativeMemoryProfilerSaProxy proxy(service);
91 return proxy.Stop(name);
92 }
93
DumpData(uint32_t fd,std::shared_ptr<NativeMemoryProfilerSaConfig> & config)94 int32_t NativeMemoryProfilerSaClientManager::DumpData(uint32_t fd,
95 std::shared_ptr<NativeMemoryProfilerSaConfig>& config)
96 {
97 CHECK_TRUE(fd != 0, RET_ERR, "NativeMemoryProfilerSaClientManager: fd is 0");
98 CHECK_NOTNULL(config, RET_ERR, "NativeMemoryProfilerSaClientManager: config is nullptr");
99 CHECK_TRUE(CheckConfig(config), RET_ERR, "CheckConfig failed");
100 auto service = GetRemoteService();
101 if (service == nullptr) {
102 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaClientManager: stop GetRemoteService failed");
103 return RET_ERR;
104 }
105 NativeMemoryProfilerSaProxy proxy(service);
106 return proxy.DumpData(fd, config);
107 }
108
GetRemoteService()109 sptr<IRemoteObject> NativeMemoryProfilerSaClientManager::GetRemoteService()
110 {
111 auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
112 if (abilityManager == nullptr) {
113 return nullptr;
114 }
115 return abilityManager->CheckSystemAbility(INativeMemoryProfilerSa::NATIVE_DAEMON_SYSTEM_ABILITY_ID);
116 }
117
CheckConfig(const std::shared_ptr<NativeMemoryProfilerSaConfig> & config)118 bool NativeMemoryProfilerSaClientManager::CheckConfig(const std::shared_ptr<NativeMemoryProfilerSaConfig>& config)
119 {
120 CHECK_NOTNULL(config, false, "NativeMemoryProfilerSaClientManager: config is nullptr");
121 if (config->duration_ == 0) {
122 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaClientManager: duration cannot be 0");
123 return false;
124 }
125 if (config->filePath_.length() >= PATH_MAX) {
126 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaClientManager: filePath_ invalid");
127 return false;
128 }
129 if (config->shareMemorySize_ == 0) {
130 config->shareMemorySize_ = config->responseLibraryMode_ ? LIB_SMS : CALL_STACK_SMS;
131 }
132 return true;
133 }
134
GetMallocStats(int fd,int pid,int type,bool printNmdOnly)135 int32_t NativeMemoryProfilerSaClientManager::GetMallocStats(int fd, int pid, int type, bool printNmdOnly)
136 {
137 CHECK_TRUE(fd != 0, RET_ERR, "NativeMemoryProfilerSaClientManager: GetMallocStats fd is 0");
138 CHECK_TRUE(pid > 0, RET_ERR, "NativeMemoryProfilerSaClientManager: GetMallocStats invalid pid");
139 CHECK_TRUE(type == 0 || type == 1 || type == ONLY_NMD, RET_ERR,
140 "NativeMemoryProfilerSaClientManager: type is invalid");
141 std::shared_ptr<NativeMemoryProfilerSaConfig> config = std::make_shared<NativeMemoryProfilerSaConfig>();
142 config->printNmd_ = true;
143 config->printNmdOnly_ = printNmdOnly;
144 if (config->printNmdOnly_) {
145 config->pid_ = static_cast<int32_t>(pid);
146 config->duration_ = NMD_DURATION;
147 config->mallocDisable_ = true;
148 config->mmapDisable_ = true;
149 config->shareMemorySize_ = NMD_SHMEM;
150 }
151 config->nmdPid_ = static_cast<uint32_t>(pid);
152 config->nmdType_ = static_cast<uint32_t>(type);
153 CHECK_NOTNULL(config, RET_ERR, "NativeMemoryProfilerSaClientManager: config is nullptr");
154 CHECK_TRUE(CheckConfig(config), RET_ERR, "CheckConfig failed");
155 auto service = GetRemoteService();
156 if (service == nullptr) {
157 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaClientManager: stop GetRemoteService failed");
158 return RET_ERR;
159 }
160 NativeMemoryProfilerSaProxy proxy(service);
161 return proxy.DumpData(fd, config);
162 }
163
StartPrintSimplifiedNmd(pid_t pid,std::vector<SimplifiedMemStats> & memStats)164 int32_t NativeMemoryProfilerSaClientManager::StartPrintSimplifiedNmd(pid_t pid,
165 std::vector<SimplifiedMemStats>& memStats)
166 {
167 CHECK_TRUE(pid > 0, RET_ERR, "NativeMemoryProfilerSaClientManager: StartPrintSimplifiedNmd invalid pid");
168 std::shared_ptr<NativeMemoryProfilerSaConfig> config = std::make_shared<NativeMemoryProfilerSaConfig>();
169 CHECK_NOTNULL(config, RET_ERR, "NativeMemoryProfilerSaClientManager: config is nullptr");
170 config->printNmd_ = true;
171 config->printNmdOnly_ = true;
172 config->pid_ = static_cast<int32_t>(pid);
173 config->duration_ = NMD_DURATION;
174 config->mallocDisable_ = true;
175 config->mmapDisable_ = true;
176 config->shareMemorySize_ = NMD_SHMEM;
177 config->nmdPid_ = static_cast<uint32_t>(pid);
178 config->nmdType_ = static_cast<uint32_t>(SIMP_NMD);
179 CHECK_TRUE(CheckConfig(config), RET_ERR, "CheckConfig failed");
180 auto service = GetRemoteService();
181 if (service == nullptr) {
182 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaClientManager: SimplifiedNmd GetRemoteService failed");
183 return RET_ERR;
184 }
185 NativeMemoryProfilerSaProxy proxy(service);
186 std::string replyStats;
187 int32_t ret = proxy.Start(config, replyStats);
188 if (ret != RET_OK) {
189 PROFILER_LOG_ERROR(LOG_CORE, "StartPrintSimplifiedNmd failed");
190 return ret;
191 }
192 size_t newlinePos = replyStats.find_first_of('\n');
193 if (newlinePos != std::string::npos) {
194 replyStats.erase(0, newlinePos + 1);
195 }
196 SimplifiedMemStats tmp;
197 std::istringstream iss(replyStats);
198 std::stringstream ss;
199 std::string line;
200 while (std::getline(iss, line, '\n')) {
201 ss.str("");
202 ss.clear();
203 ss.str(line);
204 ss >> tmp.size >> tmp.allocated >> tmp.nmalloc >> tmp.ndalloc;
205 memStats.push_back(tmp);
206 }
207 return RET_OK;
208 }
209
Start(int fd,pid_t pid,uint32_t duration,SimplifiedMemConfig & config)210 int32_t NativeMemoryProfilerSaClientManager::Start(int fd, pid_t pid, uint32_t duration, SimplifiedMemConfig& config)
211 {
212 CHECK_TRUE(fd != 0, RET_ERR, "NativeMemoryProfilerSaClientManager: fd is 0");
213 CHECK_TRUE(pid > 0, RET_ERR, "NativeMemoryProfilerSaClientManager: Simplified Start invalid pid");
214 std::shared_ptr<NativeMemoryProfilerSaConfig> nConfig = std::make_shared<NativeMemoryProfilerSaConfig>();
215 CHECK_NOTNULL(nConfig, RET_ERR, "NativeMemoryProfilerSaClientManager: config is nullptr");
216 nConfig->pid_ = static_cast<int32_t>(pid);
217 nConfig->duration_ = duration;
218 nConfig->largestSize_ = config.largestSize;
219 nConfig->secondLargestSize_ = config.secondLargestSize;
220 nConfig->maxGrowthSize_ = config.maxGrowthSize;
221 nConfig->sampleInterval_ = config.sampleSize;
222 nConfig->shareMemorySize_ = CALL_STACK_SMS;
223 nConfig->statisticsInterval_ = FIVE_MINUTES;
224 nConfig->jsStackReport_ = true;
225 nConfig->maxJsStackDepth_ = JS_STACK_DEPS;
226 auto service = GetRemoteService();
227 if (service == nullptr) {
228 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaClientManager: Simplified Start GetRemoteService failed");
229 return RET_ERR;
230 }
231 NativeMemoryProfilerSaProxy proxy(service);
232 return proxy.DumpData(fd, nConfig);
233 }
234 } // namespace OHOS::Developtools::NativeDaemon