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_service.h"
17 #include "native_memory_profiler_sa_death_recipient.h"
18 #include "iservice_registry.h"
19 #include "ipc_skeleton.h"
20 #include "trace_file_writer.h"
21 #include "socket_context.h"
22 #include "hook_common.h"
23 #include "init_param.h"
24 #include "token_setproc.h"
25 #include "accesstoken_kit.h"
26 #include "common.h"
27 #include "logging.h"
28
29 namespace OHOS::Developtools::NativeDaemon {
30 namespace {
31 constexpr int32_t TIME_BASE = 1000;
32 constexpr int32_t MAX_TASK_NUM = 4;
33 const std::string FILE_PATH_HEAD = "/data/local/tmp/native_memory_";
34 const std::string FILE_PATH_TAIL = ".htrace";
35 constexpr int32_t DELAYED_SHUTDOWN_TIME = 20;
36 constexpr int FILE_MODE = 0644;
37 constexpr int32_t SIMP_NMD = 3;
38 constexpr int32_t NMD_WAIT_MS = 100;
39 constexpr int32_t NMD_WAIT_TIMES = 50;
40 }
41
NativeMemoryProfilerSaService()42 NativeMemoryProfilerSaService::NativeMemoryProfilerSaService() : SystemAbility(NATIVE_DAEMON_SYSTEM_ABILITY_ID, true)
43 {
44 serviceName_ = "HookService";
45 serviceEntry_ = std::make_shared<ServiceEntry>();
46 if (!serviceEntry_->StartServer(DEFAULT_UNIX_SOCKET_HOOK_PATH)) {
47 serviceEntry_ = nullptr;
48 PROFILER_LOG_ERROR(LOG_CORE, "Start IPC Service FAIL");
49 return;
50 }
51 serviceEntry_->RegisterService(*this);
52 DelayedShutdown(false);
53 }
54
~NativeMemoryProfilerSaService()55 NativeMemoryProfilerSaService::~NativeMemoryProfilerSaService()
56 {
57 serviceEntry_ = nullptr;
58 }
59
StartServiceAbility()60 bool NativeMemoryProfilerSaService::StartServiceAbility()
61 {
62 sptr<ISystemAbilityManager> serviceManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
63 CHECK_NOTNULL(serviceManager, false, "serviceManager is nullptr");
64
65 static sptr<NativeMemoryProfilerSaService> native(new NativeMemoryProfilerSaService());
66 CHECK_NOTNULL(native, false, "native is nullptr");
67 int32_t result = serviceManager->AddSystemAbility(NATIVE_DAEMON_SYSTEM_ABILITY_ID, native);
68 if (result != 0) {
69 PROFILER_LOG_ERROR(LOG_CORE, "Service native memory failed to start");
70 return false;
71 }
72
73 auto abilityObject = serviceManager->AsObject();
74 CHECK_NOTNULL(abilityObject, false, "abilityObject is nullptr");
75
76 bool ret = abilityObject->AddDeathRecipient(new NativeMemoryProfilerSaDeathRecipient());
77 if (ret == false) {
78 PROFILER_LOG_ERROR(LOG_CORE, "AddDeathRecipient failed");
79 return false;
80 }
81 PROFILER_LOG_INFO(LOG_CORE, "Service native memory started successfully");
82 return true;
83 }
84
HasProfilingPermission()85 bool NativeMemoryProfilerSaService::HasProfilingPermission()
86 {
87 uint32_t callingTokenID = IPCSkeleton::GetCallingTokenID();
88 int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callingTokenID,
89 "ohos.permission.ENABLE_PROFILER");
90 if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
91 PROFILER_LOG_ERROR(LOG_CORE, "No profiling permission, please check!");
92 return false;
93 }
94 return true;
95 }
96
Start(std::shared_ptr<NativeMemoryProfilerSaConfig> & config)97 int32_t NativeMemoryProfilerSaService::Start(std::shared_ptr<NativeMemoryProfilerSaConfig>& config)
98 {
99 if (config->printNmd_) {
100 std::lock_guard<std::mutex> guard(nmdMtx_);
101 nmdPidType_[config->nmdPid_] = std::make_pair(0, config->nmdType_);
102 if (!config->printNmdOnly_) {
103 return RET_OK;
104 }
105 }
106 return StartHook(config);
107 }
108
Start(std::shared_ptr<NativeMemoryProfilerSaConfig> & config,MessageParcel & reply)109 int32_t NativeMemoryProfilerSaService::Start(std::shared_ptr<NativeMemoryProfilerSaConfig>& config,
110 MessageParcel &reply)
111 {
112 if (config->printNmd_) {
113 std::lock_guard<std::mutex> guard(nmdMtx_);
114 nmdPidType_[config->nmdPid_] = std::make_pair(0, config->nmdType_);
115 if (!config->printNmdOnly_) {
116 return RET_OK;
117 }
118 }
119 return StartHook(config, 0, reply);
120 }
121
Stop(uint32_t pid)122 int32_t NativeMemoryProfilerSaService::Stop(uint32_t pid)
123 {
124 StopHook(pid);
125 return RET_OK;
126 }
127
Stop(const std::string & name)128 int32_t NativeMemoryProfilerSaService::Stop(const std::string& name)
129 {
130 StopHook(0, name);
131 return RET_OK;
132 }
133
DumpData(uint32_t fd,std::shared_ptr<NativeMemoryProfilerSaConfig> & config)134 int32_t NativeMemoryProfilerSaService::DumpData(uint32_t fd, std::shared_ptr<NativeMemoryProfilerSaConfig>& config)
135 {
136 if (config->printNmd_) {
137 std::lock_guard<std::mutex> guard(nmdMtx_);
138 nmdPidType_[config->nmdPid_] = std::make_pair(fd, config->nmdType_);
139 if (!config->printNmdOnly_) {
140 return RET_OK;
141 }
142 }
143 if (StartHook(config, fd) == RET_ERR) {
144 close(fd);
145 return RET_ERR;
146 }
147 return RET_OK;
148 }
149
StopHook(uint32_t pid,std::string name)150 void NativeMemoryProfilerSaService::StopHook(uint32_t pid, std::string name)
151 {
152 if (!HasProfilingPermission()) {
153 PROFILER_LOG_ERROR(LOG_CORE, "StopHook failed, no profiling permission!");
154 return;
155 }
156 std::lock_guard<std::mutex> guard(mtx_);
157 std::shared_ptr<TaskConfig> config = nullptr;
158 if (pid > 0) {
159 if (auto taskIter = pidCtx_.find(pid); taskIter != pidCtx_.end()) {
160 config = taskIter->second;
161 }
162 } else if (auto taskIter = nameAndFilePathCtx_.find(name); taskIter != nameAndFilePathCtx_.end()) {
163 config = taskIter->second;
164 }
165 if (config == nullptr) {
166 PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: hook has stop, pid: %d, process name: %s",
167 pid, name.c_str());
168 return;
169 }
170
171 config->hookMgr->StopPluginSession({});
172 config->hookMgr->DestroyPluginSession({});
173 nameAndFilePathCtx_.erase(config->processName);
174 nameAndFilePathCtx_.erase(config->filePath);
175 pidCtx_.erase(config->pid);
176 if (nmdPidType_.find(config->pid) != nmdPidType_.end()) {
177 nmdPidType_.erase(config->pid);
178 }
179 if (config->isStartupMode) {
180 hasStartupMode_ = false;
181 }
182 if (config->fd > 0) {
183 close(config->fd);
184 }
185 if (--taskNum_ == 0) {
186 PROFILER_LOG_INFO(LOG_CORE, "StringViewMemoryHold clear");
187 StringViewMemoryHold::GetInstance().Clear();
188 DelayedShutdown(false);
189 }
190 }
191
GetCmdArgs(std::shared_ptr<NativeMemoryProfilerSaConfig> & config)192 std::string NativeMemoryProfilerSaService::GetCmdArgs(std::shared_ptr<NativeMemoryProfilerSaConfig>& config)
193 {
194 std::stringstream args;
195 args << "pid: " << COMMON::GetProcessNameByPid(config->pid_) << ", ";
196 args << "filter_size: " << config->filterSize_ << ", ";
197 args << "max_stack_depth: " << std::to_string(config->maxStackDepth_) << ", ";
198 args << "process_name: " << config->processName_ << ", ";
199 args << "malloc_disable: " << (config->mallocDisable_ ? "true" : "false") << ", ";
200 args << "mmap_disable: " << (config->mmapDisable_ ? "true" : "false") << ", ";
201 args << "free_stack_report: " << (config->freeStackData_ ? "true" : "false") << ", ";
202 args << "munmap_stack_report: " << (config->munmapStackData_ ? "true" : "false") << ", ";
203 args << "malloc_free_matching_interval: " << std::to_string(config->mallocFreeMatchingInterval_) << ", ";
204 args << "malloc_free_matching_cnt: " << std::to_string(config->mallocFreeMatchingCnt_) << ", ";
205 args << "string_compressed: " << (config->stringCompressed_ ? "true" : "false") << ", ";
206 args << "fp_unwind: " << (config->fpUnwind_ ? "true" : "false") << ", ";
207 args << "blocked: " << (config->blocked_ ? "true" : "false") << ", ";
208 args << "record_accurately: " << (config->recordAccurately_ ? "true" : "false") << ", ";
209 args << "startup_mode: " << (config->startupMode_ ? "true" : "false") << ", ";
210 args << "memtrace_enable: " << (config->memtraceEnable_ ? "true" : "false") << ", ";
211 args << "offline_symbolization: " << (config->offlineSymbolization_ ? "true" : "false") << ", ";
212 args << "callframe_compress: " << (config->callframeCompress_ ? "true" : "false") << ", ";
213 args << "statistics_interval: " << std::to_string(config->statisticsInterval_) << ", ";
214 args << "clock: " << std::to_string(config->clockId_) << ", ";
215 args << "sample_interval: " << std::to_string(config->sampleInterval_) << ", ";
216 args << "response_library_mode: " << (config->responseLibraryMode_ ? "true" : "false") << ", ";
217 args << "js_stack_report: " << std::to_string(config->jsStackReport_) << ", ";
218 args << "max_js_stack_depth: " << std::to_string(config->maxJsStackDepth_) << ", ";
219 args << "filter_napi_name: " << config->filterNapiName_ << ", ";
220 args << "nmd_pid: " << std::to_string(config->nmdPid_) << ", ";
221 args << "nmd_type: " << std::to_string(config->nmdType_) << ", ";
222 return args.str();
223 }
224
StartHookLock(std::shared_ptr<NativeMemoryProfilerSaConfig> & config,uint32_t fd,std::shared_ptr<HookManager> & hook,std::string & args)225 int32_t NativeMemoryProfilerSaService::StartHookLock(std::shared_ptr<NativeMemoryProfilerSaConfig>& config,
226 uint32_t fd, std::shared_ptr<HookManager>& hook,
227 std::string& args)
228 {
229 std::lock_guard<std::mutex> guard(mtx_);
230 if (config->filePath_.empty() && fd == 0) {
231 std::string filePathStr = (config->pid_ > 0) ? std::to_string(config->pid_) : config->processName_;
232 config->filePath_ = FILE_PATH_HEAD + filePathStr + FILE_PATH_TAIL;
233 }
234 PROFILER_LOG_INFO(LOG_CORE, "file path: %s", config->filePath_.c_str());
235
236 if (!CheckConfig(config, fd)) {
237 COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_MSG_EMPTY,
238 "check config failed");
239 return RET_ERR;
240 }
241
242 if (fd == 0) {
243 auto retFile = COMMON::CheckNotExistsFilePath(config->filePath_);
244 if (!retFile.first) {
245 PROFILER_LOG_INFO(LOG_CORE, "%s:check file path %s fail", __func__, config->filePath_.c_str());
246 COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_INVALID_PATH,
247 "check file path failed");
248 return RET_ERR;
249 }
250 int fdTemp = open(retFile.second.c_str(), O_RDWR | O_CREAT, FILE_MODE);
251 CHECK_TRUE(fdTemp >= 0, RET_ERR, "Failed to open file(%s)", config->filePath_.c_str());
252 fd = static_cast<uint32_t>(fdTemp);
253 }
254 std::shared_ptr<TraceFileWriter> writeFile = nullptr;
255 if (config->printNmdOnly_) {
256 writeFile = std::make_shared<TraceFileWriter>(0);
257 } else {
258 writeFile = std::make_shared<TraceFileWriter>(fd);
259 }
260 CHECK_NOTNULL(writeFile, RET_ERR, "Failed to create TraceFileWriter");
261 writeFile->SetTimeSource();
262
263 hook->RegisterWriter(writeFile);
264 hook->SetSaMode(true);
265 hook->SetHookConfig(config);
266 hook->SetSaServiceConfig(true, false);
267 if (config->pid_ > 0) {
268 std::lock_guard<std::mutex> nmdGuard(nmdMtx_);
269 if (nmdPidType_.find(config->pid_) != nmdPidType_.end()) {
270 hook->SetNmdInfo(nmdPidType_[config->pid_]);
271 }
272 }
273 if (hook->CreatePluginSession() != RET_OK) {
274 COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_FAIL,
275 "create pluginsession failed");
276 return RET_ERR;
277 }
278 if (!config->printNmdOnly_) {
279 hook->WriteHookConfig();
280 }
281 hook->StartPluginSession();
282
283 int32_t timerFd = scheduleTaskManager_.ScheduleTask(
284 [this, config] { this->StopHook(config->pid_, config->processName_); },
285 config->duration_ * TIME_BASE,
286 true);
287 if (timerFd == -1) {
288 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaService Start Schedule Task failed");
289 COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_FAIL,
290 "start schedule task failed");
291 return RET_ERR;
292 }
293
294 std::shared_ptr<TaskConfig> configCtx =
295 std::make_shared<TaskConfig>(hook, config->pid_, config->processName_, config->filePath_, timerFd,
296 config->startupMode_, fd);
297 CHECK_NOTNULL(hook, RET_ERR, "Failed to create TaskConfig");
298 if (!hasStartupMode_ && config->startupMode_) {
299 hasStartupMode_ = true;
300 startupModeProcessName_ = config->processName_;
301 }
302
303 if (configCtx->pid > 0) {
304 pidCtx_[configCtx->pid] = configCtx;
305 } else if (!configCtx->processName.empty()) {
306 nameAndFilePathCtx_[configCtx->processName] = configCtx;
307 }
308
309 if (fd == 0) {
310 nameAndFilePathCtx_[configCtx->filePath] = configCtx;
311 }
312 ++taskNum_;
313 DelayedShutdown(true);
314 COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_SUCC, "success");
315 return RET_OK;
316 }
317
StartHook(std::shared_ptr<NativeMemoryProfilerSaConfig> & config,uint32_t fd)318 int32_t NativeMemoryProfilerSaService::StartHook(std::shared_ptr<NativeMemoryProfilerSaConfig>& config, uint32_t fd)
319 {
320 auto args = GetCmdArgs(config);
321 if (!HasProfilingPermission()) {
322 COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_NO_PERMISSION,
323 "no profiling permission");
324 PROFILER_LOG_ERROR(LOG_CORE, "StartHook failed, no profiling permission!");
325 return RET_ERR;
326 }
327 if (config == nullptr) {
328 return RET_ERR;
329 }
330 std::shared_ptr<HookManager> hook = std::make_shared<HookManager>();
331 CHECK_NOTNULL(hook, RET_ERR, "Failed to create HookManager");
332
333 return StartHookLock(config, fd, hook, args);
334 }
335
WaitSimplifiedNmdTimeout(uint32_t times,std::shared_ptr<HookManager> & hook,MessageParcel & reply)336 static int32_t WaitSimplifiedNmdTimeout(uint32_t times, std::shared_ptr<HookManager>& hook, MessageParcel &reply)
337 {
338 uint32_t cnt = 0;
339 while ((!hook->nmdComplete_) && (cnt < times)) {
340 std::this_thread::sleep_for(std::chrono::milliseconds(NMD_WAIT_MS));
341 cnt++;
342 }
343 if (!hook->nmdComplete_) {
344 PROFILER_LOG_ERROR(LOG_CORE, "WaitSimplifiedNmdTimeout, %d ms", times * NMD_WAIT_MS);
345 return RET_ERR;
346 }
347 WRITESTRING(reply, hook->simplifiedNmd_, RET_ERR);
348 return RET_OK;
349 }
350
StartHook(std::shared_ptr<NativeMemoryProfilerSaConfig> & config,uint32_t fd,MessageParcel & reply)351 int32_t NativeMemoryProfilerSaService::StartHook(std::shared_ptr<NativeMemoryProfilerSaConfig>& config,
352 uint32_t fd, MessageParcel &reply)
353 {
354 auto args = GetCmdArgs(config);
355 if (!HasProfilingPermission()) {
356 COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_NO_PERMISSION,
357 "no profiling permission");
358 PROFILER_LOG_ERROR(LOG_CORE, "StartHook failed, no profiling permission!");
359 return RET_ERR;
360 }
361 if (config == nullptr) {
362 return RET_ERR;
363 }
364 std::shared_ptr<HookManager> hook = std::make_shared<HookManager>();
365 CHECK_NOTNULL(hook, RET_ERR, "Failed to create HookManager");
366
367 int32_t ret = StartHookLock(config, fd, hook, args);
368 if (ret != RET_OK) {
369 return ret;
370 }
371
372 if (config->nmdType_ == SIMP_NMD) {
373 return WaitSimplifiedNmdTimeout(NMD_WAIT_TIMES, hook, reply);
374 }
375 return RET_OK;
376 }
377
CheckConfig(std::shared_ptr<NativeMemoryProfilerSaConfig> & config,uint32_t fd)378 bool NativeMemoryProfilerSaService::CheckConfig(std::shared_ptr<NativeMemoryProfilerSaConfig>& config, uint32_t fd)
379 {
380 if (taskNum_ + 1 > MAX_TASK_NUM) {
381 PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: Support up to 4 tasks at the same time");
382 return false;
383 }
384
385 if (hasStartupMode_ && config->startupMode_) {
386 PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: tasks with an existing startup mode, name: %s",
387 startupModeProcessName_.c_str());
388 return false;
389 }
390
391 if (config->pid_ > 0) {
392 config->processName_.clear();
393 if (pidCtx_.find(config->pid_) != pidCtx_.end()) {
394 PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: hook has started, pid: %d", config->pid_);
395 return false;
396 }
397 } else if (!config->processName_.empty()) {
398 if (nameAndFilePathCtx_.find(config->processName_) != nameAndFilePathCtx_.end()) {
399 PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: hook has started, process name: %s",
400 config->processName_.c_str());
401 return false;
402 }
403 } else {
404 PROFILER_LOG_ERROR(LOG_CORE, "The PID and process name are not configured");
405 return false;
406 }
407
408 if (fd > 0) {
409 return true;
410 }
411
412 if (!config->filePath_.empty()) {
413 if (nameAndFilePathCtx_.find(config->filePath_) != nameAndFilePathCtx_.end()) {
414 PROFILER_LOG_ERROR(LOG_CORE,
415 "NativeMemoryProfilerSaService: File %s is being used.", config->filePath_.c_str());
416 return false;
417 }
418 } else {
419 PROFILER_LOG_ERROR(LOG_CORE, "The file path are not configured");
420 return false;
421 }
422 return true;
423 }
424
FillTaskConfigContext(int32_t pid,const std::string & name)425 void NativeMemoryProfilerSaService::FillTaskConfigContext(int32_t pid, const std::string& name)
426 {
427 std::lock_guard<std::mutex> guard(mtx_);
428 if (auto iter = pidCtx_.find(pid); iter != pidCtx_.end()) {
429 iter->second->processName = name;
430 nameAndFilePathCtx_[name] = iter->second;
431 if (iter->second->isStartupMode) {
432 hasStartupMode_ = false;
433 }
434 } else if (auto it = nameAndFilePathCtx_.find(name); it != nameAndFilePathCtx_.end()) {
435 it->second->pid = pid;
436 pidCtx_[pid] = it->second;
437 if (it->second->isStartupMode) {
438 hasStartupMode_ = false;
439 }
440 } else {
441 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaService: fill TaskConfig context failed");
442 }
443 }
444
ProtocolProc(SocketContext & context,uint32_t pnum,const int8_t * buf,const uint32_t size)445 bool NativeMemoryProfilerSaService::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf,
446 const uint32_t size)
447 {
448 if (size != sizeof(int)) {
449 return false;
450 }
451 int peerConfig = *const_cast<int *>(reinterpret_cast<const int *>(buf));
452 if (peerConfig == -1) {
453 return false;
454 }
455
456 std::string filePath = "/proc/" + std::to_string(peerConfig) + "/cmdline";
457 std::string bundleName;
458 if (!LoadStringFromFile(filePath, bundleName)) {
459 PROFILER_LOG_ERROR(LOG_CORE, "Get process name by pid failed!, pid: %d", peerConfig);
460 return false;
461 }
462 bundleName.resize(strlen(bundleName.c_str()));
463
464 if (bundleName.substr(0, 2) == "./") { // 2: size, Command line programs will be prefixed with "./"
465 bundleName = bundleName.substr(2); // 2: point
466 }
467 FillTaskConfigContext(peerConfig, bundleName); // Save the relevant context for subsequent inspection
468
469 std::lock_guard<std::mutex> guard(mtx_);
470 if (auto iter = pidCtx_.find(peerConfig); iter != pidCtx_.end()) {
471 auto [eventFd, smbFd] = iter->second->hookMgr->GetFds(peerConfig, bundleName);
472 iter->second->hookMgr->SetPid(peerConfig);
473 if (eventFd == smbFd) {
474 PROFILER_LOG_ERROR(LOG_CORE,
475 "Get eventFd and smbFd failed!, name: %s, pid: %d", bundleName.c_str(), peerConfig);
476 return false;
477 }
478 PROFILER_LOG_INFO(LOG_CORE,
479 "ProtocolProc, receive message from hook client, and send hook config to process %d, name: %s",
480 peerConfig, bundleName.c_str());
481 ClientConfig clientConfig;
482 iter->second->hookMgr->GetClientConfig(clientConfig);
483 if (iter->second->hookMgr->GetNoDataQueueFlag()) {
484 clientConfig.freeEventOnlyAddrEnable = true;
485 }
486 clientConfig.isSaMode = true;
487 context.SendHookConfig(reinterpret_cast<uint8_t *>(&clientConfig), sizeof(clientConfig));
488 context.SendFileDescriptor(smbFd);
489 context.SendFileDescriptor(eventFd);
490 iter->second->hookMgr->ResetStartupParam();
491 } else {
492 PROFILER_LOG_ERROR(LOG_CORE, "ProtocolProc: send config failed");
493 return false;
494 }
495 return true;
496 }
497
DelayedShutdown(bool cancel)498 void NativeMemoryProfilerSaService::DelayedShutdown(bool cancel)
499 {
500 if (cancel) {
501 scheduleTaskManager_.UnscheduleTask(delayedShutdownTimerFd_);
502 delayedShutdownTimerFd_ = -1;
503 } else {
504 int32_t timerFd = scheduleTaskManager_.ScheduleTask(
505 []() {
506 int ret = SystemSetParameter("hiviewdfx.hiprofiler.native_memoryd.start", "0");
507 if (ret < 0) {
508 PROFILER_LOG_ERROR(LOG_CORE, "DelayedShutdown close sa failed");
509 } else {
510 PROFILER_LOG_INFO(LOG_CORE, "DelayedShutdown close sa success");
511 }
512 },
513 DELAYED_SHUTDOWN_TIME * TIME_BASE, true);
514 if (timerFd == -1) {
515 PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaService:DelayedShutdown Schedule Task failed");
516 return;
517 }
518 delayedShutdownTimerFd_ = timerFd;
519 }
520 }
521 } // namespace OHOS::Developtools::NativeDaemon